維尼的蜂巢

RealTime??!! It’s amazing!!!!

dll使用的問題 十一月 8, 2006

Filed under: VC++/C++/C — kevinlin @ 3:19 下午

其實對於使用DLL心理一直有個疙瘩,因為DLL裡的一個靜態(全域)物件,我不知道怎麼知道他們到底有沒有被銷毀,雖然知道他們真的有被建構,但是到底有沒有進去解構,真是摸不著腦袋,老是懷疑他們會一直佔著記憶體不放,這真是個很大的問題。

一直到這兩天翻了MSDN,上面有提到 C/C++ run-time library code performs the DLL startup sequence,也有一些詳細的說明,總算了了我的不安。

在調用DLL時,我們知道靜態物件會被建構,但是DLL我們知道程式裡面DllMain()可以是空的,進入點既然是空的,那誰來建構解構呢??現在要來找出兇手…..

到底誰來呼叫這些函式呢?何時呼叫的呢?答案是:startup code,在進入 DllMain 之前。你也許認為一切都是從 DllMain 開始的,但在此之前, C runtime DLL startup code calls 了建構函式。如果你打開 crtdll.c 看看 CRT’s DLL initialization sequence (這個檔案在\VS.NET\VC7\crt\src),你會發現下面的函式:

BOOL WINAPI _DllMainCRTStartup(...) { 
  if ( /* DLL_PROCESS_ATTACH */ ) { 
     _CRT_INIT(...); // initialize CRT including ctors 
     DllMain(...); 
  } 
  ... 
}

現在來對所發生的重要細節進行了簡化:_DllMainCRTStartup 呼叫另一個 crtdll 函數_CRT_INIT,然後才到 DllMain。_CRT_INIT initializes the C runtime後,然後去跑你的所有靜態物件的建構函式。_CRT_INIT 是如何知道要做哪些建構函式呢?是編譯器產生了一個列表。所以當應用程式使用你的 C++ DLL 時,其加載順序如下:

  1. The app loads your DLL (LoadLibrary)
  2. LoadLibrary calls _DllMainCRTStartup
  3. _DllMainCRTStartup calls _CRT_INIT
  4. _CRT_INIT calls static ctors
  5. _DllMainCRTStartup calls DllMain
  6. DllMain does more initialization
  7. The app calls DLL functions

這邊來介紹什麼是_DLLMainCRTStartup

為了使用 CRT (CRT,C Run time Library) 的 DLL 版本(多執行緒),DLL必須指定 _DLLMainCRTStartup為入口函數,DLL 的初始化函數必須是 DLLMain。
_DLLMainCRTStartup 完成以下任務:當process或thread(Attach) 到 DLL 時為C Runtime Data 分配空間和初始化並且建構全域的 “C++"物件,當process或thread(Detach) 時,清理 C Runtime Data 並且銷毀全域 “C++" 物件。它還call DLLMain 和 RawDLLMain 函數。
其實DLL又衍生了一個問題,關係到DLL怎麼造成系統崩潰

欲知後情、請待下回分曉

 

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 變更 )

Twitter picture

You are commenting using your Twitter account. Log Out / 變更 )

Facebook照片

You are commenting using your Facebook account. Log Out / 變更 )

Google+ photo

You are commenting using your Google+ account. Log Out / 變更 )

連結到 %s