對DllMain的誤解 轉

2021-07-02 02:52:02 字數 3075 閱讀 6670

向原文致敬

一直以來對dllmain的了解也就侷限於,實驗性的在dllmain裡面寫上: cout<<"dll執行"<

我在dllmain裡面這樣寫的**:

[cpp]view plain

copy

bool

apientry dllmain( 

hmodule

hmodule,  

dword

ul_reason_for_call,  

lpvoid

lpreserved  

)    

while

(!g_is_stop)  

return

true;  

}  

載入dll 的**如下:

[cpp]view plain

copy

hmodule

hmodule = loadlibrary(strdllfullpath.c_str());  

if(hmodule)  

else  

程式執行的結果很出我的意料之外:

程式瘋狂的new 記憶體,然後顯示:dll載入失敗

我覺得不可思議,為什麼都開始執行dllmain裡面的**了,函式還返回載入失敗。

後面查了下相關資料,發現原來dllmain裡面的**是在loadlibrary的時候呼叫的,執行完dllmain裡面的**,如果dllmain返回true,那麼loadlibrary才會返回成功。 而我一直以為,dllmain是在載入dll成功,loadlibrary返回才開始呼叫的。這告訴我一定要仔細閱讀msdn上面的相關說明。

接著在網上搜了下dllmain的相關資料,如下:

跟exe有個main或者winmain入口函式一樣,dll也有乙個入口函式,就是dllmain。以「dllmain」為關鍵字,來看看msdn幫助文件怎麼介紹這個函式的。

thedllmainfunction is an optional method of entry into a dynamic-link library (dll)

。(簡要翻譯:對於乙個dll模組,dllmain函式是可選的。)這句話很重要,很多初學者可能都認為乙個動態鏈結庫肯定要有dllmain函式。其實不然,像很多僅僅包含資源資訊的dll是沒有dllmain函式的。

系統是在什麼時候呼叫dllmain函式的呢?靜態鏈結時,或動態鏈結時呼叫loadlibrary和freelibrary都會呼叫dllmain函式。dllmain的第三個引數fdwreason指明了系統呼叫dll的原因,它可能是dll_process_attach、dll_process_detach、dll_thread_attach和dll_thread_detach。以下從這四種情況來分析系統何時呼叫了dllmain。            

1.2.1 dll_process_attach

大家都知道,乙個程式要呼叫dll裡的函式,首先要先把dll檔案對映到程序的位址空間。要把乙個dll檔案對映到程序的位址空間,有兩種方法:靜態鏈結和動態鏈結的loadlibrary或者loadlibraryex。

當乙個dll檔案被對映到程序的位址空間時,系統呼叫該dll的dllmain函式,傳遞的fdwreason引數為dll_process_attach。這種呼叫只會發生在第一次對映時。如果同乙個

程序後來為已經對映進來的dll再次呼叫loadlibrary或者loadlibraryex,作業系統只會增加dll的使用次數,它不會再用dll_process_attach呼叫dll的dllmain函式。不同程序用loadlibrary同乙個dll時,每個程序的第一次對映都會用dll_process_attach呼叫dll的dllmain函式。

可參考dllmaintest的dll_process_attach_test函式。

1.2.2 dll_process_detach

◆freelibrary解除dll對映(有幾個loadlibrary,就要有幾個freelibrary)

◆程序結束而解除dll對映,在程序結束前還沒有解除dll的對映,程序結束後會解除dll對映。(如果程序的終結是因為呼叫了terminateprocess,系統就不會用dll_process_detach來呼叫dll的dllmain函式。這就意味著dll在程序結束前沒有機會執行任何清理工作。)

注意:當用dll_process_attach呼叫dll的dllmain函式時,如果返回false,說明沒有初始化成功,系統仍會用dll_process_detach呼叫dll的dllmain函式。因此,必須確保沒有清理那些沒有成功初始化的東西。

可參考dllmaintest的dll_process_detach_test函式。

1.2.3 dll_thread_attach

當程序建立一線程時,系統檢視當前對映到程序位址空間中的所有dll檔案映像,並用值dll_thread_attach呼叫dll的dllmain函式。

新建立的執行緒負責執行這次的dll的dllmain函式,只有當所有的dll都處理完這一通知後,系統才允許程序開始執行它的執行緒函式。

注意跟dll_process_attach的區別,我們在前面說過,第n(n>=2)次以後地把dll映像檔案對映到程序的位址空間時,是不再用dll_process_attach呼叫dllmain的。而dll_thread_attach不同,程序中的每次建立執行緒,都會用值dll_thread_attach呼叫dllmain函式,哪怕是執行緒中建立執行緒也一樣。

1.2.4 dll_thread_detach

如果執行緒呼叫了exitthread來結束執行緒(執行緒函式返回時,系統也會自動呼叫exitthread),系統檢視當前對映到程序空間中的所有dll檔案映像,並用dll_thread_detach來呼叫dllmain函式,通知所有的dll去執行執行緒級的清理工作。

注意:如果執行緒的結束是因為系統中的乙個執行緒呼叫了terminatethread,系統就不會用值dll_thread_detach來呼叫所有dll的dllmain函式。

綜上,如果要在dll裡面幹點什麼事情,最好還是先定義乙個匯出函式,在這個匯出函式裡面幹自己想幹的事。然後loadlibrary 成功後,在getprocaddr得到函式指標,再呼叫這個匯出函式比較好。

對SDN的誤解

誤解一 sdn一定要使用openflow協議來配置 面 openflow只是發展最早 目前影響力最大的南向介面,但是並不是唯一的。誤解二 sdn要求硬體 面的標準化 這只是openflow的要求,並不是sdn的要求。誤解三 sdn裝置可以代替所有裝置 誤解四 sdn得到了所有廠商的支援 誤解五 sd...

對敏捷開發的誤解

對敏捷開發的誤解 誤解一 敏捷對人的要求很高 很多人在嘗試實施敏捷時說 敏捷對人的要求太高了,我們沒有這樣的條件,我們沒有這樣的人,因此我們沒法敏捷。可是,敏捷對人的要求真的那麼高麼?軟體歸根到底還是一種創造性活動,開發人員的技術水平和個人能力對軟體的質量還是起著決定性的作用,各種過程與方法只是幫助...

DllMain重複定義的錯誤

今天建立winsole dll工程,從mfc工程中拷貝過來檔案,遇到如下問題 linking.nafxcwd.lib dllmodul.obj error lnk2005 dllmain 12 already defined in libcmtd.lib dllmain.obj nafxcwd.li...