DLL THREAD DETACH 認識誤區

2021-06-21 16:55:49 字數 2839 閱讀 9530

dll 裡面使用tls (local thread storage ) 的常見做法是:在dllmain的dll_process_attach/dll_thread_attach 被呼叫的時候為每個執行緒(thread)分配記憶體,而在dll_thread_detach/dll_process_detach 被呼叫的時候釋放記憶體。 msdn文章《using thread local storage in a dynamic-link library》 上有這樣的示例**。

[cpp]view plain

copy

print?

bool

winapi dllmain(

hinstance

hinstdll, 

// dll module handle

dword

fdwreason,                    

// reason called

lpvoid

lpvreserved)                 

// reserved

return

true;  

}  

這段**認為dll_thread_detach 總是會被呼叫, 但實際情況並非如此。在某些情況下dll_thread_detach並不會被呼叫, 結果造成記憶體洩漏。 接下來做2個簡單實驗說明這個問題。

實驗**:

[cpp]view plain

copy

print?

typedef

void

(__stdcall *fnsleep)();  

void

calltestdll()  

dword

winapi threadproc( 

lpvoid

lpparam)  

g_hdllmodule = ::loadlibrary(_t("testdll.dll"

));  

atltrace("[thread %d] loadlibrary=0x%.8x/n"

, ::getcurrentthreadid());  

calltestdll();  

const

intmax_thread = 2;  

handle

hthread[max_thread];  

for(

inti=0; i < max_thread; i++)  

sleep(max_thread * 1000);  

::freelibrary(g_hdllmodule);  

輸出結果1:

[cpp]view plain

copy

print?

[thread 4976] dll_process_attach                

//主線程

[thread 4976] loadlibrary=0x0ecbf9d4  

[thread 4976] dosleep() in dll  

[thread 7860] dll_thread_attach                  //createthread 產生的執行緒

[thread 736] dll_thread_attach                    //createthread 產生的執行緒

[thread 736] dosleep() in dll  

[thread 7860] dosleep() in dll  

[thread 736] dll_thread_detach  

[thread 7860] dll_thread_detach  

[thread 4976] dll_process_detach                //主線程

以上輸入結果我們看到每個thread 呼叫dll函式dosleep 立即結束,這時候dll_thread_detach 被正常呼叫。 這時只要候稍微改一下**,會看到完全不同的結果。

[cpp]view plain

copy

print?

dword

winapi threadproc( 

lpvoid

lpparam)  

輸出結果2:

[cpp]view plain

copy

print?

[thread 7448] dll_process_attach              

//主線程

[thread 7448] loadlibrary=0x0b1cf9d4  

[thread 7448] dosleep() in dll  

[thread 6872] dll_thread_attach  

[thread 6556] dll_thread_attach  

[thread 6556] dosleep() in dll  

[thread 6872] dosleep() in dll  

[thread 7448] dll_process_detach             //主線

我們發現,createthread 產生的執行緒並沒有呼叫dll_thread_detach 。

結論:如果是執行緒在dll被解除安裝(呼叫freelibrary) 之前結束,則dll_thread_detach 會被呼叫。 如果執行緒在dll解除安裝之後結束,則dll_thread_detach 不會被呼叫。

本文**hellocpp:

DLL THREAD DETACH 認識誤區

dll 裡面使用tls local thread storage 的常見做法是 在dllmain的dll process attach dll thread attach 被呼叫的時候為每個執行緒 thread 分配記憶體,而在dll thread detach dll process detach...

誤GHOST 誤一鍵恢復 災難應急方案

適用 個人機 部分品牌機 具備一鍵恢復功能 災難過程及症狀 1 個人機採用ghost恢復系統,恢復系統後發現整個硬碟變成乙個大分割槽,原擴充套件分割槽全部不見。2 用品牌機帶一鍵恢復光碟恢復系統後,整個硬碟變成乙個大分割槽,原擴充套件分割槽全部不見。3 本例不適用恢復系統時,選錯目標分割槽 本例不適...

誤GHOST 誤一鍵恢復 災難應急方案

適用 個人機 部分品牌機 具備一鍵恢復功能 災難過程及症狀 1 個人機採用ghost恢復系統,恢復系統後發現整個硬碟變成乙個大分割槽,原擴充套件分割槽全部不見。2 用品牌機帶一鍵恢復光碟恢復系統後,整個硬碟變成乙個大分割槽,原擴充套件分割槽全部不見。3 本例不適用恢復系統時,選錯目標分割槽 本例不適...