程序最早执行的函数其实并不是main,在main函数之前会有一系列初始化的操作(通常是由链接器等完成的)。比如在windows中,这个函数是mainCRTStartup,这个函数是链接器执行以初始化运行时库的,此函数又会调用CRTInit函数,该函数会对C全局变量、C内存分配以及C++中的全局类对象和构造函数进行初始化工作。
一、利用全局类对象或者变量
在C++编程中,可以利用定义全局类对象或全局变量,来实现让代码先于main()之前执行。另一种方式是定义一个全局变量为函数运行后的结果,那么该函数就会用于初始化,会先于main执行。
示例代码
#include <iostream>
#include <stdio.h>
using std::cout;
using std::endl;
class ClassInit
{
public:
ClassInit()
{
cout << "ClassInit() constructor" << endl;
}
~ClassInit()
{
cout << "ClassInit() destructor" << endl;
}
};
int init_befor_main()
{
cout << "init_befor_main()" << endl;
return 0;
}
ClassInit cls;
int g_nValue = init_befor_main();
int main()
{
std::cout << "This is main function.\n" << endl;
return 0;
}
输出如下:
ClassInit() constructor
init_befor_main()
This is main function.
ClassInit() destructor
二、利用pragma data_seg(“.CRT$XIU”)
CRTInit函数中会做一些初始化工作,包括C库、C的初始化函数、C++库、C++的初始化函数等。C和C++分别有一张表来保存初始化函数指针,每个表又会使用2个指针来明确范围。在初始化过程中,__CRTInit函数会一次调用这两个表中的函数,所以如果我们能把要执行的函数放在这两个表中,那么就可以达到在main之前执行代码的目的了。
C初始化函数表的范围是:[ __xi_a, __xi_a ]
C++初始化函数表的范围是:[ __xc_a, __xc_z]
我们在具体执行的时候,通过定义特殊的段名称“.CRT
X
I
U
”和“
.
C
R
T
XIU”和“.CRT
XIU”和“.CRTXCU”,把要执行的函数放在段中。
链接器就会形成如下的C初始化函数表:
[__xi_a, …, before1(xiu), …, __xi_z]
以及C++初始化函数表:
[__xc_a, …, before2(xcu), …, __xc_z]
示例代码
#include <iostream>
#include <stdio.h>
using std::cout;
using std::endl;
int before_main(void)
{
printf("before main!\n");
return 0;
}
typedef int init_func();
#pragma data_seg(".CRT$XIU")
static init_func *before[] = { before_main };
#pragma data_seg()
int main()
{
std::cout << "This is main function.\n" << endl;
return 0;
}
输出结果
需要注意:通过 pragma data_seg(“.CRT$XIU”) 方式,会比全局类对象或者变量先执行。
before main!
This is main function.
三、MinGW编译环境
在Linux环境的C编程中,可以利用__attribute关键字定义constructor和destructor,其中前者会在main函数之前执行,后者会在main函数之后执行。
#include <QCoreApplication>
#include <stdio.h>
__attribute((constructor)) void run_before_main()
{
printf("run before main!\n");
}
__attribute((destructor)) void run_after_main()
{
printf("run after main!\n");
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
printf("this is main function.\n");
return 0;
return a.exec();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)