#include <stdio.h>
#include <stdlib.h>
static void before(void) __attribute__ ((constructor));
static void after(void) __attribute__ ((destructor));
static void middle(void);
static void before()
{
fprintf(stderr, "In %s %d\n", __func__, __LINE__);
}
static void after()
{
fprintf(stderr, "In %s %d\n", __func__, __LINE__);
}
static void middle()
{
fprintf(stderr, "In %s %d\n", __func__, __LINE__);
}
int main(void)
{ printf("bengin\n");
atexit(middle);
printf("end\n");
return 0;
}
通过指定
static void before(void) __attribute__ ((constructor));
表明这个函数应该在main之前执行
static void after(void) __attribute__ ((destructor));
表明函数在main之后执行
atexit表明函数在退出的时候执行
执行结果:
In before 10
bengin
end
In middle 20
In after 15
实际上,在可执行文件被加载之后,控制权立即交给由编译器插入的Start函数,它将对后面这些全局变量进行准备:
_osver 操作系统的构件编号
_winmajor 操作系统的主版本号
_winminor 操作系统的次版本号
_winver 操作系统完全版本号
__argc 命令行参数个数
__argv 指向参数字符串的指针数组
_environ 指向环境变量字符串的指针数组
Start函数初始化堆并调用main函数.mian函数返回之后,Start函数调用Exit函数结束该进程.
启动函数Start的源代码在:
crt0.c Microsoft Visual C++
c0w.asm Borladn C++
二、 我们看下面的例子:
main函数执行之前,主要就是初始化系统相关资源: 1.设置栈指针 2.初始化static静态和global全局变量,即data段的内容 3.将未初始化部分的赋初值:数值型short,int,long等为0,bool为FALSE,指针为NULL,等等,即.bss段的内容 4.运行全局构造器,估计是C++中构造函数之类的吧 5.将main函数的参数,argc,argv等传递给main函数,然后才真正运行main函 |