标签:完成 names after 全局 -o 内存 nat 初始化 结构
来源:《周哥教IT.C语言深学活用》https://ke.qq.com/course/242707#tuin=a71606
我们在学习C/C++语言的时候,通常认为main函数是整个程序执行的开始。实际上,在main函数之前,会有一系列初始化的操作,这样的操作通常是由链接器等完成的。具体说来,程序最早执行的函数其实并不是main,在windows中,是mainCRTStartup,这个函数是链接器执行以初始化运行时库的,此函数又会调用CRTInit函数,该函数会对C全局变量、C内存分配以及C++中的全局类对象和构造函数进行初始化工作。所以想要在main函数之前执行一些自己的代码,是有可能的。
1. Linux环境下利用gcc的__attribute关键字
在Linux环境的C编程中,可以利用__attribute关键字定义constructor和destructor,其中前者会在main函数之前执行,后者会在main函数之后执行。
代码如下:
1 #include <stdio.h> 2 3 __attribute((constructor)) void before_main() 4 { 5 printf("before main!\n"); 6 } 7 8 __attribute((destructor)) void after_main() 9 { 10 printf("after main!\n"); 11 } 12 13 int main(void) 14 { 15 printf("This is main function.\n"); 16 return 0; 17 }
运行结果:
natalie@ubuntu:~/Desktop/zhou_it_c/before_main$ gcc before_main.c -o before_main
natalie@ubuntu:~/Desktop/zhou_it_c/before_main$ ./before_main
before main!
This is main function.
after main!
2. Windows环境下利用#pragma预定义
上面我们说过CRTInit函数中会做一些初始化工作,包括C库、C的初始化函数、C++库、C++的初始化函数等。C和C++分别有一张表来保存初始化函数指针,每个表又会使用2个指针来明确范围。在初始化过程中,__CRTInit函数会一次调用这两个表中的函数,所以如果我们能把要执行的函数放在这两个表中,那么就可以达到在main之前执行代码的目的了。
C初始化函数表的范围是:[ __xi_a, __xi_a ] C++初始化函数表的范围是:[ __xc_a, __xc_z]
我们在具体执行的时候,通过定义特殊的段名称“.CRT$XIU”和“.CRT$XCU”,把要执行的函数放在段中。链接器就会形成日下的C初始化函数表:
[__xi_a, ..., before1(xiu), ..., __xi_z]
以及C++初始化函数表:
[__xc_a, ..., before2(xcu), ..., __xc_z]
代码如下:
#include <stdio.h> int before_main(void) { printf("before main!\n"); return 0; } typedef int func(); #pragma data_seg(".CRT$XIU") static func *before[] = { before_main }; #pragma data_seg() int main(void) { printf("This is main function.\n"); return 0; }
3. C++编程中利用定义全局类对象or全局变量
mainCRTStartup会对全局对象a初始化,也就是说a的构造含税会先于main执行,所以只需要在a的构造函数中定义我们要执行的函数。
另一种方式是定义一个全局变量为函数运行后的结构,那么该函数就会用于初始化,会先于main执行。
代码如下:
1 #include <iostream> 2 using namespace std; 3 using std::cout; 4 5 int func() 6 { 7 cout <<"before main: func()" << endl; 8 return 0; 9 } 10 11 class A 12 { 13 public: 14 A() 15 { 16 cout << "A() constructor" << endl; 17 } 18 ~A() 19 { 20 cout << "A() destructor" << endl; 21 } 22 }; 23 24 A a; 25 26 int g_iValue = func(); 27 28 int main(void) 29 { 30 cout << "This is main function." << endl; 31 return 0; 32 }
运行结果:
A() constructor
before main: func()
This is main function.
A() destructor
标签:完成 names after 全局 -o 内存 nat 初始化 结构
原文地址:http://www.cnblogs.com/nata1ier/p/7822767.html