MFC 基礎:靜態載入DLL ,main()、main全域變數、dllMain()、dllMain全域變數的一些說明,mfcdllmain
現今的程式在大部分情況下,都或多或少引用了一些功能庫。因此瞭解動態庫DLL的載入和初始化,有利於避免一些依賴問題的出現。
動態庫的載入有 動態載入 和靜態載入兩種方式。現僅對靜態載入的方式進行一些跟蹤,來得出一些順序上的結果。
程式主程入口:int main(char argc, char *argv[]); DLL庫的入口 :BOOL WINAPI DllMain(DWORD dwReason, LPVOID /*lpReserved*/); 注, 1),如果 DLL 沒有聲明自己的入口函數:DllMain,系統會調用一個預設入口函數:DllMain 2),如果程式過程中建立新子線程,同樣會調用入口DLL 入口函數:DllMain 3),如果強制終止 進程/線程,則不會調用入口函數:DllMain(所以在某些情況下強制終止線程會出現記憶體流失的情況) DLL的跟蹤代碼
class CGlobalT{public:CGlobalT(){printf("CGlobalT constructor called\n");}~CGlobalT(){printf("~CGlobalT destructor called\n");}protected:private:};static CGlobalT m_global;BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved){switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:printf("DLL process attached\n");break;case DLL_THREAD_ATTACH:printf("DLL thread attached");break;case DLL_THREAD_DETACH:printf("DLL thread detached");break;case DLL_PROCESS_DETACH:printf("DLL process detached");break;}return TRUE;}
建立了DLL入口函數:DllMain()、靜態全域變數:
m_global通過跟蹤全域對象的建構函式調用和介面調用,來確定調用順序。
主程的跟蹤代碼
#pragma comment(lib,"..\\..\\build\\dllTest.lib")#include "..\..\dllTest\dllTest\dllTest.h"#include "ThreadInterface.h"class CMainGlobal{public:CMainGlobal(){printf("CMainGlobal constructor called\n");}~CMainGlobal(){printf("~CMainGlobal destructor called\n");}protected:private:};static CMainGlobal m_mainGlobal;int main(int argc, char *argv[]){func();CExportClass exportClass;exportClass.DoAction();CThreadInterface threadC;threadC.StartThread();Sleep(500);threadC.ExistThread();return EXIT_SUCCESS;}
建立了主程入口:main() 和靜態全域變數:m_mainGlobal同樣通過跟蹤全域對象的 建構函式調用和 mian調用,來確定調用順序
跟蹤得到的調用順序
1)DLL 全域變數 constructor 調用
2)DllMain()入口函數調用 :DLL_PROCESS_ATTACH
3)main 全域變數 constructor 調用
4)main() 函數調用5)DllMain()入口函數調用:DLL_THREAD_ATTACH.(ThreadC 為線程對象,啟動線程後的動作)
6)DllMain()入口函數調用:DLL_THREAD_DETACH
7)main()函數退出
8)main() 全域變數 destructor 調用
9)DllMain()入口函數調用:DLL_PROCESS_DETACH
10)DLL 全域變數 destructor 調用
通過以上跟蹤的順序得出的一些結論:1)程式載入靜態DLL的動作:全域變數初始化、dll入口調用,
均先於main全域靜態變數載入2)載入DLL過程和主程調用過程,都是先初始化全域變數後調用入口函數3)介面退出和DLL卸載過程剛好相反,調用帶入的參數不一樣
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。如有著作權問題,請留言。