静态加载DLL ,main()、main全局变量、dllMain()、dllMain全局变量的一些说明

来源:互联网 发布:淘宝上传宝贝教程视频 编辑:程序博客网 时间:2024/05/04 12:06
  现今的程序在大部分情况下,都或多或少引用了一些功能库。因此了解动态库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卸载过程刚好相反,调用带入的参数不一样




2 0
原创粉丝点击