我们知道一般的C/C++ 的程序是从main函数开始的,然后在main函数结束后程序结束。但是不然,在main函数开始执行前,已经有其他的指令被执行了。
为了程序的顺利执行,首先要初始化执行环境,比如堆分配初始化(malloc, free) ,线程子系统等,这里先提一下:C++ 的全局对象构造函数就是在这一时期被执行的。即C++ 的全局对象构造函数在main 函数之前执行,而C++ 全局对象的析构函数在main函数之后被执行。
linux 系统中,一般程序的入口是“ _start ", 这个函数是Linux系统库(Glibc)的一部分。当我们的程序与Glibc库链接在一起形成最终的可执行文件以后,这个函数就是程序的初始化部分的入口,程序的初始化部分完成一系列初始化过程以后,就会调用main函数来执行程序的主体。在main函数执行完成以后,返回到初始化部分,会进行一系列清理工作,然后结束进程。
对于有些场合,程序的一些特性的操作必须在main函数之前执行,还有一些操作必须在Mian函数之后执行,这里再提一下C++ .因为最具代表性的就是C++ 的全局对象的构造与析构函数。因此ELF(linux里一种文件格式)文件定义了两种段涉及到了这种信息。
§ .init 该段里边保存的是可执行命令,它构成了进程的初始化代码。因此,当一个程序开始运行时,在main函数被调用前Glibc的初始化部分安排执行这个段中的代码。
§ .fini 该段保存着进程终止代码指令。因此,当一个程序的main函数正常退出时,Glibc会安排执行这个段中的代码。
因此,这两个段.init 和 .fini的存在有着特别的目的,如果一个函数放到了.init 段,在main函数执行前,系统就会执行它。同理,假如一个函数放到了.fini段,在main函数返回后函数就会被执行。利用这两个特征,C++ 的全局构造函数和析构函数就是这样来的。
《程序员的自我修养》