程序员的自我修养: 全局构造/析构函数是怎样调用的?
2010-03-11 10:50
323 查看
全局构造/析构函数与C/C++运行库
主要以MSVC CRT来说:
大致的过程如下:
__xc_a, __xc_z分别处于两个特殊的段里, 并具有long,read属性.
因此这两条pragma指令实际在obj文件里生成了名为.CRT$XCA和.CRT$XCAZ的两个段.
__declspec(allocate(x))将其分别分配到对应段中
当链接的时候,链接器会将所有相同属性的段合并,注意的是,合并到输出段时,是根据字符表顺序依次排序.
由于.CRT$XC*这些段的属性都是只读的,且名字很相近,最后往往被放到只读段中,成为.rdata的一部分.
这样就形成了存储所有全局初始化函数的地址的数组.
还有:.CRT$XC*段中存放的是该obj文件的全局初始化函数的地址.所以最后形成的是一个函数地址数组.
结果: Hello world!
MSVC CRT 析构
是当调用初始化函数的时候,用atexit函数注册了析构函数的执行地址.
主要以MSVC CRT来说:
大致的过程如下:
mainCRTStartup() { ... _initterm(__xc_a, __xc_z); } typedef void (__cdecl * _PVFV)(); static void __cdecl _initterm(_PVFV* pfbegin, _PVFV* pfend) { while(pfbegin < pfend) { if(*pfbegin != NULL) (**pfbegin)(); ++pfbegin; } } //__xc_a, __xc_z的定义 _CRTALLOC(".CRT$XCA") _PVFV __xc_a[] = {NULL}; _CRTALLOC(".CRT$XCZ") _PVFV __xc_z[] = {NULL}; //_CRTALLOC的定义 #pragma section(".CRT$XCA", long, read) #pragma section(".CRT$XCZ", long, read) ... #define _CRTALLOC(x) __declspec(allocate(x))
__xc_a, __xc_z分别处于两个特殊的段里, 并具有long,read属性.
因此这两条pragma指令实际在obj文件里生成了名为.CRT$XCA和.CRT$XCAZ的两个段.
__declspec(allocate(x))将其分别分配到对应段中
当链接的时候,链接器会将所有相同属性的段合并,注意的是,合并到输出段时,是根据字符表顺序依次排序.
由于.CRT$XC*这些段的属性都是只读的,且名字很相近,最后往往被放到只读段中,成为.rdata的一部分.
这样就形成了存储所有全局初始化函数的地址的数组.
还有:.CRT$XC*段中存放的是该obj文件的全局初始化函数的地址.所以最后形成的是一个函数地址数组.
#include <iostream> using namespace std; #define SECNAME ".CRT$XCV" #pragma section(SECNAME, long, read) void foo() { cout << "hello world!" << endl; } typedef void (__cdecl * _PVFV)(); __declspec(allocate(SECNAME)) _PVFV dummy[] = {foo, foo}; int main() { return 0; }
结果: Hello world!
MSVC CRT 析构
是当调用初始化函数的时候,用atexit函数注册了析构函数的执行地址.
相关文章推荐
- 全局对象和函数内静态对象调用构造析构函数差异
- 全局对象和函数内静态对象调用构造析构函数差异
- C++ 构造/析构函数中调用虚函数的问题
- 构造/析构函数中不要调用虚函数
- 全局对象和函数内静态对象调用构造析构函数差异
- 不要在构造和析构函数中调用虚函数
- 拷贝构造,构造函数,析构函数的调用顺序
- 由一道面试题引发的“血案”(静态变量,虚函数,构造/析构函数调用顺序等)
- 一道面试题(静态变量,虚函数,构造/析构函数调用顺序等)
- 浅谈C++--绝不在构造和析构函数中调用virtual函数
- C++对象数组调用构造/析构函数的方法
- 编写高质量代码——避免在构造析构函数中调用虚函数
- 虚函数与继承子类构造与析构函数调用问题
- C++全局对象的析构函数有时候没有被调用?非也!(编译器为VC++6.0)
- C++构造与析构(19) - 显式地调用构造函数和析构函数
- 基类派生类构造析构函数调用顺序、成员初始化和销毁顺序
- Effective C++条款9:绝不在构造和析构函数过程中调用virtual函数
- 读书笔记《Effective c++》 条款09 绝不在构造和析构函数中调用virtual函数
- C++ 笔记(二) —— 不要在构造和析构函数中调用虚函数
- 深度解析-->c++中构造函数,拷贝构造,赋值运算符重载,析构函数的调用情况