C++ 全局对象初始化

         C++ 程序中,全局对象的初始化是在主函数([w]main() or [w]WinMain)被调用之前被初始化的。

          Visual studio 编译器在编译时会判断编译选项 "-subsystem" 来指点输出程序是 "console" 还是 "windows",同时还会判断程序中所使用的字符集是否是 unicode 的。 所以 visaul studio 的程序会有四个不同的程序入口 (entry)。

        

程序入口表
subsystem\Unicode Unicode(yes) Non-unicode
"console" wmainCRTStartup(wmain) mainCRTStartup (main)
"windows" wWinMainCRTStartup(wWinMain) WinMainCRTStartup(WinMain)

       通常在通过向导创建的程序的入口是 _tmain ,这是采用 TCHAR 封装之后的版本, _tmain 对于两个不同的函数定义,根据当前是否是unicode。

            #define _tmain      wmain
            #define _tmain      main

        看 mainCRTStartup 的代码,可知道全局对象的初始化是通过调用 _initterm 函数完成的,这个函数在 doexit 中还会被调用。 这个函数的输入是函数指针的首地址和末地址。 这个函数只是简单的调用传递进去的函数指针。

         在对象被创建的时候,会传递创建对象的函数指针,在函数被销毁的适合,会传递对象析构的函数指针给 _initterm 函数。

         如果一个 C++ 的全局对象有构造函数的话,那么这个对象在声明的时候,会被转化成为一段代码。 我写了一个简单的程序来测试:

          

#include <iostream>

using namespace std;

class Test
{
public:
  Test() {
    int i, j ;

    for(i  = 1 ; i < 9 ; i ++ ) {
      for( j = 1 ; j <= i ; j ++ ) {
        cout << " " << i << " x " << j << " = " << i * j ;
      }
      cout << endl;
    }
  }
};

Test  objTest;
int _tmain(int argc, _TCHAR* argv[])
{
	return 0;
}
   在代码 Test objTest 处,由于 Test 对象有构造函数,那么声明的全局对象 objTest 会被转换成为一段代码:

push        ebp  
mov         ebp,esp 
sub         esp,0C0h 
push        ebx  
push        esi  
push        edi  
 lea         edi,[ebp-0C0h] 
mov         ecx,30h 
mov         eax,0CCCCCCCCh  //这段代码是在debug 版下为了防止stack 溢出所添加的调试代码
rep stos    dword ptr es:[edi] 
mov         ecx,offset objTest (41A148h) //对象的 this 指针是通过 ecx 传递的
call        Test::Test (4111D1h) //调用构造函数
pop         edi  
pop         esi  
pop         ebx  
 add         esp,0C0h 
cmp         ebp,esp 
call        @ILT+425(__RTC_CheckEsp) (4111AEh)  // Visual studio 好像是从 2005 之后,引入了 RTC (Runtime check )
mov         esp,ebp 
pop         ebp  
ret    
       这一段代码会被存放在程序的代码段中,在程序被加载之后,会初始化成很多函数指针,在 mainCRTStartup 被调用的时候,会把这些函数指针传递给 _initterm 函数。 _initterm 函数会在 main 函数调用之前被调用,在全局对象初始化结束之后, main 函数会被调到。 上面的测试中,在 Test::Test 执行之后,main 函数会被调用执行。

    上面所做的分析是编译器相关的。

你可能感兴趣的:(C++,c,windows,测试,编译器)