刪除在DLL中創建的對象時,我需要一些關於運行時/堆問題的說明。在我回答我的問題之前,需要一些介紹...刪除在DLL中創建的對象
在我的項目中,一個DLL(由它的名稱指定)返回一個新的Grabber對象。在我的代碼的早期版本中,DLL導出這樣的功能:
extern "C"
__declspec(dllexport) Grabber* CreateGrabber(string settings)
{
return new SomeSpecificGrabber(settings);
}
在EXE我用這樣的靜態函數來創建一個新的抓取對象:
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);
}
在EXE一個抓取對象的生命週期由智能指針管理:
shared_ptr<Grabber> myGrabberObj = shared_ptr<Grabber>(createGrabberObject("SomeGrabber.DLL", "Settings"));
這一切,只要我編譯EXE並與/MDd
設置(VC++ 2010)的DLL工作得很好,WHI ch意味着EXE和DLL使用相同的堆。
現在我想用/MTd
設置編譯我的解決方案。有了這個,我得到了一個類型爲_CrtIsValidHeapPointer
的運行時斷言,用於傳遞給DLL的設置字符串對象。這是有道理的,因爲DLL試圖刪除在EXE中創建的字符串對象。而且他們不再使用相同的堆。
我解決此問題得到了通過更改導出的DLL函數一點點(的const char*
代替string
):
extern "C"
__declspec(dllexport) Grabber* CreateGrabber(const char* settings)
{
return new SomeSpecificGrabber(settings);
}
而在createGrabberObject
我通過grabberSettings.c_str()
,而不是grabberSettings
的DLL功能。
現在一切正常了。但現在我的第一個問題:爲什麼我不能在myGrabberObj
被刪除時得到_CrtIsValidHeapPointer
斷言?該對象是從DLL內部創建的,但是從EXE中刪除(通過智能指針)。爲什麼我在這裏沒有與上面的字符串對象相同的問題?
我想一個乾淨的解決方案是該DLL還出口函數是這樣的:
extern "C"
__declspec(dllexport) void DeleteGrabber(Grabber* grabber)
{
delete grabber;
}
然後我也有我的EXE這一個DLL調用DeleteGrabber靜態函數:
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);
}
這個靜態函數可以自動然後由智能指針叫做:
shared_ptr<Grabber> myGrabberObj = shared_ptr<Grabber>(createGrabberObject("SomeGrabber.DLL", "Settings"),
boost::bind(deleteGrabberObject, "SomeGrabber.DLL", _1));
這也適用。但是這裏來了我的第二個問題:靜態函數createGrabberObject
和deleteGrabberObject
都加載DLL。這是否意味着創建了兩個不同的堆,因爲加載了這個DLL的兩個實例(那麼這個解決方案根本無法解決我的問題)?或者這兩個靜態函數使用相同的堆?
我希望有人能解釋這裏發生了什麼...
謝謝!這真的很快! –