Necesito alguna aclaración con respecto a los problemas de tiempo de ejecución/montón al eliminar un objeto que se creó en una DLL. Necesita alguna introducción antes de llegar a mis preguntas ...Eliminación de un objeto que se creó en una DLL
En mi proyecto, una DLL (que se especifica por su nombre) devuelve un nuevo objeto de Grabber. En una versión anterior de mi código, el archivo DLL exporta una función como esta:
extern "C"
__declspec(dllexport) Grabber* CreateGrabber(string settings)
{
return new SomeSpecificGrabber(settings);
}
en el EXE He utilizado una función estática como este para crear un nuevo objeto en forma de mano:
static Grabber* createGrabberObject(const std::string& grabberType, const std::string& grabberSettings)
{
FARPROC hProc = 0;
// load dll with the name of grabberType
HMODULE hDLL = LoadLibrary(grabberType.c_str());
// get address for CreateGrabber function
hProc = GetProcAddress(hDLL, "CreateGrabber");
// instantiate a function pointer of our type and typecast the address
// of the CreateGrabber function to this type
CreateGrabberFunctionType CreateGrabberFunction = (CreateGrabberFunctionType)hProc;
// call CreateGrabber in DLL to get a Grabber object
return CreateGrabberFunction(grabberSettings);
}
en el EXE el tiempo de vida de un objeto en forma de mano es administrado por un puntero inteligente:
shared_ptr<Grabber> myGrabberObj = shared_ptr<Grabber>(createGrabberObject("SomeGrabber.DLL", "Settings"));
Esta todo funcionó bien siempre y cuando compilé el EXE y DLL con el ajuste /MDd
(VC++ 2010), WHI ch significa que EXE y DLL usaron el mismo montón.
Ahora quiero compilar mi solución con la configuración /MTd
. Con esto obtuve una afirmación en tiempo de ejecución del tipo _CrtIsValidHeapPointer
para el objeto de cadena de configuración que pasé a la DLL. Esto tiene sentido porque el DLL intenta eliminar un objeto de cadena que se creó en el EXE. Y ya no usan el mismo montón.
que tiene alrededor de este problema cambiando la función DLL exportado un poco (en lugar de const char*
string
):
extern "C"
__declspec(dllexport) Grabber* CreateGrabber(const char* settings)
{
return new SomeSpecificGrabber(settings);
}
Y en createGrabberObject
que pase grabberSettings.c_str()
en lugar de grabberSettings
a la función DLL.
Ahora todo vuelve a funcionar bien. Pero ahora viene mi primera pregunta: ¿Por qué no obtengo la aserción _CrtIsValidHeapPointer
cuando se borra myGrabberObj
? El objeto se creó desde el DLL, pero se elimina desde el EXE (mediante el puntero inteligente). ¿Por qué no tengo el mismo problema aquí que con el objeto de cadena anterior?
supongo una solución limpia sería que la DLL exporta también una función como esta:
extern "C"
__declspec(dllexport) void DeleteGrabber(Grabber* grabber)
{
delete grabber;
}
Entonces tendría también una función estática en mi EXE que llama a DeleteGrabber en un archivo DLL:
static void deleteGrabberObject(const std::string& grabberType, Grabber* grabber)
{
FARPROC hProc = 0;
// load dll with the name of grabberType
HMODULE hDLL = LoadLibrary(grabberType.c_str());
// get address for DeleteGrabber function
hProc = GetProcAddress(hDLL, "DeleteGrabber");
// instantiate a function pointer of our type and typecast the address
// of the DeleteGrabber function to this type
DeleteGrabberFunctionType DeleteGrabberFunction = (DeleteGrabberFunctionType)hProc;
// call DeleteGrabber in DLL
DeleteGrabberFunction(grabber);
}
Esta función estática podría entonces ser llamado automáticamente por el puntero inteligente:
shared_ptr<Grabber> myGrabberObj = shared_ptr<Grabber>(createGrabberObject("SomeGrabber.DLL", "Settings"),
boost::bind(deleteGrabberObject, "SomeGrabber.DLL", _1));
Esto también funciona. Pero aquí viene mi segunda pregunta: Las funciones estáticas createGrabberObject
y deleteGrabberObject
ambas cargan la DLL. ¿Significa que se crean dos montones diferentes porque se cargan dos instancias de la DLL (entonces esta solución no resolvería mi problema en absoluto)? ¿O estas dos funciones estáticas usan el mismo montón?
Espero que alguien pueda explicar lo que está pasando aquí ...
Gracias! ¡Esto fue realmente rápido! –