有一個DLL,由主(桌面)應用程序通過Windows.LoadLibrary
動態加載。這是因爲有很多類似的DLL,只有少數幾個需要在運行時加載。所以靜態鏈接不是一種選擇。Delphi DLL是否預定用於加載程序鎖定?
問題是,加載其中一個DLL時,每隔一段時間主應用程序就會掛起。請注意,這個問題很可能會發生在每一個人身上。可能是因爲他們有很多共同的代碼庫。
問題似乎是一個裝載機鎖(see this SO answer on what it is)。我找到了一段通用代碼,它在啓動時使用的begin...end
部分library
-unit(即project.dpr
)中的所有DLL都被使用,其中GetModuleHandle
和GetProcAddress
被使用。
我發現,這是一個完全用的DLL DONT,作爲begin...end
-section DLL的項目文件實際上是在圖書館的DllMain
功能及調用這些函數可導致死鎖(命名爲裝載機鎖) 。我讀到Microsoft Best Practice Guide。
因此,我重建我的代碼,這些電話稍後調用,當Windows.LoadLibrary
的呼叫已完成。
不幸的是,懸掛問題依然存在。 :-(
我運行了調試器,然後逐步完成了每一行初始化操作,甚至在執行一行代碼之前調用了這些初始化代碼。我確定,很多第三方代碼違反了指南的做法,什麼不能在DLL初始化代碼做:
- TMS組件包
- JEDI組件庫
- OmniThreadLibrary
- Indy組件
以上所有動態加載initialization
中的其他DLL,或通過GetProcAddress
請求過程指針。我認爲這些調用導致掛載當我的DLL加載。
難道只有少數德爾菲開發人員知道initialization
的危險嗎?我能做些什麼呢?
根據鏈接到的文檔,在DLL初始化期間,可以安全地使用'GetModuleHandle()'和'GetProcAddress()'。 Indy在運行時動態加載多個DLL,但是它們中的任何一個都不應該加載到任何「初始化」節中,它們在實際調用DLL函數時會根據需要動態加載。但是我剛剛發現了一個正在加載到'initialization'部分的DLL(zlib),所以我現在修復了這個問題。 –
請參閱api函數文檔中的「庫」部分。 GetModuleHandle和GetProcAddress是內核函數。 –
因此,這[網站](https://blog.barthe.ph/2009/07/30/no-stdlib-in-dllmai/)錯誤關於'GetModuleHandle'?它說*「這個」加載程序鎖定「在任何時候加載一個程序庫時被使用,而且當使用像GetModuleHandle()或GetModuleFileName()這樣的函數時。」* –