/*
清理堆分配的資源這是我的理解是,它加載一個或多個動態鏈接庫(DLL)到其地址空間Windows進程將與所有加載的共享地址空間DLL--意味着這些DLL可以讀取和寫入進程地址空間中的任何內存。但是,如果在堆上分配對象,則每個模塊(無論是.exe
還是某個進程的加載的DLL)都從它自己的堆中分配。由於這個原因,對於執行分配的同一個堆釋放內存非常關鍵。問題跨越一個Windows DLL模塊邊界
這一切都對我有意義,我認爲我可以使用std::unique_ptr
來幫助保持組織。這是我使用的方法。 (我沒有我的編譯器方便的時刻,但我覺得這些片段/僞代碼將足夠清楚傳達了我的意圖:
*/
Library.h
class ILibrary
{
public:
virtual void DoStuff() = 0;
};
struct Deleter
{
void operator()(ILibrary *p)
{
delete p;
}
};
typedef std::unique_ptr<ILibrary, Deleter> Ptr;
//*MyLibrary.dll*
//Includes Library.h
//Exports:
void GetMyLibrary(Ptr & library)
{
library = Ptr(new MyLibrary); // point (1)
}
//**Program.exe**
//Includes Library.h
//Imports MyLibrary.dll (GetMyLibrary export)
int main()
{
Ptr local;
MyLibrary->GetMyLibrary(local);
local->DoStuff();
} // heap corruption on cleanup
你可以看到我的庫和主程序都使用了相同的頭文件Library.h,我創建了變量local
來保存指向我的庫的指針GetMyLibrary方法(在DLL中調用)分配並指定new unique_ptr
給我傳入的引用。我在「第一點」使用了賦值,因爲我想從cont繼續使用Deleter用於清理的DLL的分機,而不是最初分配給我的主程序中的local
變量的Deleter。意思是,當本地超出範圍時,我希望它的清理能夠觸發DLL的Deleter,而不是最初分配給它的那個Deleter(即我使用library = Ptr(new MyLibrary)
而不是library.reset(new MyLibrary)
,因爲我希望從DLL的上下文中調用Deleter )
無論如何,該程序似乎工作,除了在清理過程中,當本地unique_ptr
破壞,我得到一個堆腐敗異常(在調試中),導致我相信我刪除了錯誤的堆(即。 unique_ptr
不符合我的預期)
最終,我最終以另一種方式解決了問題,看起來更清潔,但我只是很好奇爲什麼上面的方法失敗了?
「**堆」 - 這是你的問題的很大一部分。就Windows而言,**堆由['GetProcessHeap'](https://msdn.microsoft.com/en-us/library/windows/desktop/aa366569(v = vs.85) .aspx),並且EXE和DLL之間共享堆_is_(因此名稱爲「進程堆」)。 – MSalters
感謝您的鏈接,我會閱讀。 – charunnera