在這種情況下,我的動態加載的DLL由Windows資源管理器加載,以便爲文件/文件夾屬性頁面添加一個新的屬性表(新選項卡)。如何在動態加載的DLL中正確實現(C++)線程本地存儲?
一個簡單的例子是StrmExt.dll(download source)。在這個例子中(微軟提供的源代碼)dll不使用線程本地存儲(TLS),因此在同時加載多個屬性頁時會導致嚴重問題。
在審查源的DLL所需要的一個線程基變量(該文件的文件路徑)...
static TCHAR g_szFile[MAX_PATH];
的代碼這一行改爲:
_declspec (thread) TCHAR g_szFile[MAX_PATH];
。 ..使DLL支持多線程,因此支持propertysheet的多個實例。不過,我知道這個改變只會被Windows Vista和更新版本支持(Windows 7的測試非常積極)。例如,XP不支持動態加載的庫......這是known to crash the application。 (見最後一段)。
爲了在XP上運行我不能使用這個聲明。我懷疑我需要提高自己的DLL入口點來自:
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
_Module.Init(ObjectMap, hInstance, &LIBID_STRMEXTLib);
DisableThreadLibraryCalls(hInstance);
}
else if (dwReason == DLL_PROCESS_DETACH)
_Module.Term();
return TRUE; // ok
}
...到這樣的事情......如先前看到here
struct ThreadData {
static TCHAR g_szFile[MAX_PATH];
};
...
DWORD g_dwThreadIndex;
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance,
DWORD dwReason, LPVOID /*pReserved*/)
{
ThreadData* pData;
switch (dwReason) {
case DLL_PROCESS_ATTACH:
g_dwThreadIndex = ::TlsAlloc();
if (g_dwThreadIndex == TLS_OUT_OF_INDEXES)
return FALSE;
// execute the DLL_THREAD_ATTACH code
case DLL_THREAD_ATTACH:
// allocate memory for this thread
pData = (ThreadData*) ::LocalAlloc(LPTR, sizeof(ThreadData));
if (pData == 0)
return FALSE;
::TlsSetValue(g_dwThreadIndex, (LPVOID) pData);
break;
case DLL_THREAD_DETACH:
// release memory for this thread
pData = (ThreadData*) ::TlsGetValue(g_dwThreadIndex);
if (pData != 0)
::LocalFree((HLOCAL) pData);
break;
case DLL_PROCESS_DETACH:
// release memory for this thread
pData = (ThreadData*) ::TlsGetValue(g_dwThreadIndex);
if (pData != 0)
::LocalFree((HLOCAL) pData);
// release the TLS index
::TlsFree(g_dwThreadIndex);
break;
}
return TRUE;
}
該DLL的第一次加載時工作正常是否創建1或2個線程。在釋放dll之後,資源管理器在下一次加載庫時崩潰。
我誤解了什麼?我注意到原始開發者故意在dll進程附加通知時禁用線程通知。爲什麼?
DisableThreadLibraryCalls(hInstance);
在先進的感謝。
DisableThreadLibraryCalls只是一個優化。 「Explorer崩潰」不是一個合適的問題描述,你必須更好地記錄崩潰細節。 – 2012-03-03 19:48:23
公平的評論。我知道這是一個優化選項,但是如果還有其他原因,我們很好奇。我使用的XP系統目前位於另一個系統的虛擬機上,我將在下一天看到提供異常報告。但是,我在示例中詢問通知代碼。它看起來是否正確,特別是在Windows資源管理器的上下文中?即進程附加邏輯如何正確執行線程附加邏輯?而且,TLS是否在線程分離和進程分離上正確釋放? – clsturgeon 2012-03-03 20:10:49
很明顯,您必須刪除對「DisableThreadLibraryCalls」的調用才能接收「DLL_THREAD_ATTACH」和「DLL_THREAD_DETACH」。除此之外,我想你可能會因爲DllMain的變幻莫測而出現一些泄漏。 – 2012-03-03 21:03:19