2012-04-14 97 views
3

所以我有一個我用C++編寫的DLL。 但是,它使用GlobalAlloc()分配內存。爲了避免內存泄漏,我想跟蹤這些分配並取消分配所有這些對DLL的破壞。C++ DLL卸載析構函數?

有沒有什麼辦法可以編寫一個函數,當我的DLL被卸載時會被調用? 我能想到的一件事是在我的DLL中創建一個全局對象,並在其析構函數中寫入內存免費調用,但這似乎是矯枉過正。 我的另一個想法是在DLL卸載時只依靠操作系統釋放內存,但這看起來很髒。

謝謝

+0

調用LPCSTR GetCSV()函數時分配內存。基本上,我將本地std字符串的內存複製到我使用GlobalAlloc()分配的內存中,以確保調用方在函數返回後可以訪問內存。我添加了一些代碼來清除舊的調用GetCSV()的內存,但我不會處理卸載DLL時的最後一種情況,因爲這顯然是爲我自動完成的。這篇文章(http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx)(由answerers鏈接),非常好。 – Amil 2012-04-15 03:32:03

回答

6

有沒有什麼辦法可以編寫一個函數,當我的DLL被卸載時會被調用?有一件事我能想到的是建立在我的DLL一個全局對象,並在其析構函數

這可能寫入內存免費電話,但我相信什麼時候你的對象的析構函數將被稱爲將是不確定的。

你可能會對DLL_PROCESS_DETACH感興趣,雖然你應該避免在DllMain做任何重要的事情,但似乎在這裏可以取消分配資源。注意注意事項:

由於DLL加載失敗,進程終止或FreeLibrary調用導致DLL從流程中卸載時,系統不會調用DLL的入口點函數與進程的各個線程的DLL_THREAD_DETACH值一起使用。該DLL只發送一個DLL_PROCESS_DETACH通知。 DLL可以藉此機會清除DLL已知的所有線程的所有資源。

處理DLL_PROCESS_DETACH時,只有在動態卸載DLL(lpReserved參數爲NULL)時,DLL才應釋放資源(如堆內存)。如果進程正在終止(lpvReserved參數爲非NULL),除當前線程之外的進程中的所有線程已經退出或已通過對ExitProcess函數的調用顯式終止,這可能會留下一些進程資源,如堆處於不一致的狀態。在這種情況下,DLL清理資源並不安全。相反,該DLL應該允許操作系統回收內存。

您可能需要詳細說明爲什麼你的DLL可以抓住內存,如果你的DLL創造了無數的對象,他們應該有一個明確的生命週期,並在其生命的最後清洗自己了。

如果它們不是物體(即,內存被分配並通過函數返回給調用者)爲什麼不把責任放回到使用DLL的人身上?他們可以釋放內存。終端服務庫遵循這種模式(WTSFreeMemory)。

如果資源是長期存在的,並且必須存在,那麼讓消費者控制庫的生命週期。編寫兩個函數:MyFrameworkStartupMyFrameworkShutdown。 Winsock遵循這種模式(WSAStartupWSACleanup)。

我的另一個想法是隻依賴操作系統,以釋放內存時DLL卸載,但這似乎很髒。

You'll be okay if the process is exiting

不要擔心釋放內存;當進程地址空間被破壞時它將全部消失。不要擔心關閉手柄;當進程句柄表被銷燬時,句柄會自動關閉。不要嘗試調用其他DLL,因爲那些其他DLL可能已經收到它們的DLL_PROCESS_DETACH通知,在這種情況下,它們可能會像Delphi對象的行爲不正常一樣運行,如果在析構函數運行後嘗試使用它。

請務必在實施「無所事事」策略之前閱讀整篇文章並進行評論和理解。

+0

謝謝!太棒了。特別是關於不用擔心釋放內存的注意事項。 – Amil 2012-04-15 03:28:09

2

如何/何時分配內存?通常,最好的選擇是嘗試保持某種對稱性(構造函數分配,析構函數解除分配,或者在DLL加載時分配內存,卸載DLL時釋放內存)。

在任何情況下,如果要在卸載DLL時收到通知,請查看DllMain函數,特別是DLL_PROCESS_DETACH參數。

+1

根據您給出的鏈接,運行時庫提供的標準DllMain調用全局對象的構造函數/析構函數。因此,我猜只是在適當的構造函數/析構函數中使用DLL中的全局對象應該足夠了。 – celtschk 2012-04-15 00:17:16

+0

感謝您的迴應!當調用'LPCSTR GetCSV()'函數時分配內存。基本上,我將本地std字符串的內存複製到我使用'GlobalAlloc()'分配的內存中,以確保我的調用方在函數返回後可以訪問內存。我添加了一些代碼來清除舊的調用內存到'GetCSV()',但我不會處理卸載DLL時的最後一種情況,因爲這顯然是爲我自動完成的。 – Amil 2012-04-15 03:31:26