前几天看到一个朋友,想要在main执行之前执行一段代码,当时记得不太清,就不敢贸然回答,怕误导别人。等弄清楚了,却发现那个帖子不见了,汗。
先看几个小例子:
1.
#include <stdio.h>
int a = 3;
int main(int argc, char* argv[])
{
printf("The value of a is %d./n", a);
getchar();
return 0;
}
2.
#include <iostream>
#include <string>
using namespace std;
class Test
{
public:
Test()
{
cout << "This is a test" << endl;
}
};
Test t;
int main(int argc, char* argv[])
{
getchar();
return 0;
}
3.
#include <iostream>
#include <string>
using namespace std;
void foo()
{
cout << "After main...." << endl;
}
int main(int argc, char* argv[])
{
atexit(&foo);
cout << "End of main" << endl;
return 0;
}
4. 在上面任意一个例子中的main函数中下一个断点,执行,等中断的时候打开Call Stack。
-----------------------------------
C/C++课上,老师都告诉我们,C/C++程序从main函数开始执行,main函数返回时,程序就结束了。
执行完上面的几个小程序,想必诸位可能有点被愚弄了许久的感觉吧?
1. 在main执行之前,变量a就已经是我们初始化的值3了,谁帮我们做的?
2. main什么都没做,只是在等待输入并退出,而t却被实例化了。
3. main已经结束了,foo函数居然被执行了!
显然,操作系统在装入我们编译出来的程序时,最先执行的代码,并不是main函数的第一行,而是另外一些代码,这些代码为程序的执行作好了一切准备:准备好输入输出,准备好运行库,这也就是为什么main还没有执行的时候,我们的全局变量就已经初始化好了,printf,cout,*alloc之类的运行时库都已经可以使用,命令行参数已经等着我们获取的原因。main函数返回时,它又记录main的返回值,执行登记的atexit函数,做一下大扫除,比如卸载运行库,释放内存之后结束进程并将main的返回值交给操作系统。
一般而言,我们将上述代码称为入口点函数。对MS VC++而言,这个函数的名称是mainCRTStartup,这个函数干了两件事,一是初始化security cookie,主要是为了防止栈溢出;二是调用__tmainCRTStartup,在这里作进一步的初始化操作,有兴趣地话,可以看看VS 2010附带的crt源代码,位置在Microsoft Visual Studio 10.0/VC/crt/src/crtexe.c,这里贴上部分代码。
__declspec(noinline)
int
__tmainCRTStart