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

本文详细探讨了静态链接下DLL的加载与初始化流程,并通过跟踪全局变量构造与接口调用,明确了DLL加载与主程序之间的调用顺序。揭示了DLL加载、线程创建及卸载过程中的关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  现今的程序在大部分情况下,都或多或少引用了一些功能库。因此了解动态库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卸载过程刚好相反,调用带入的参数不一样




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值