首页
社区
课程
招聘
C++里面关于类的构造的诡异问题
发表于: 2009-10-28 07:15 4521

C++里面关于类的构造的诡异问题

2009-10-28 07:15
4521
先调用非静态类成员函数,再调用类构造函数~

class CTest
{
public:
        CTest(){
                printf("CTest\n",0);
        }
        int GetValue(){
                printf("GetValue\n",0);
                return 2;
        }
protected:
private:
};

extern CTest g_Test;
int a = g_Test.GetValue(), b = g_Test.GetValue();
CTest g_Test;

int _tmain(int argc, _TCHAR* argv[])
{
        getchar();
        return 0;
}

测试在
Windows下vc6,vs2003,vs2005,vs2008,Borland C++6,Mingw,Linux下G++下都是
GetValue
GetValue
CTest

粗略看了下,都是在main函数前编译器初始化一些全局变量的时候出的问题,是否可以当成是C++编译器的bug?附件上传之~

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 247
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
结果确实是这样
但是这不是bug
在c/c++中
extern CTest g_Test;
并不是生成一个对象
而仅仅是一个声明,说明CTest g_Test在后面定义,注意:在这里并没有分配空间和资源
所以,没有调用构造函数,只是调用成员函数
在后面CTest g_Test;才调用构造函数
2009-10-28 09:43
0
雪    币: 178
活跃值: (159)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
问题就在这里,没有对象,如何调用非静态成员函数,调试看过来,貌似是
_initterm((void)* *, (void)* *)
0043D550  push        ebp  
0043D551  mov         ebp,esp
0043D553  mov         eax,dword ptr [pfbegin] ;这个值在开始会指向一个类似虚函数表的东东,会根据这个找到在类实例化之前的成员函数,包括全局类的构造,这个值通过堆栈里面的一个特定的值进行4字节递增遍历得到
0043D556  cmp         eax,dword ptr [pfend]
0043D559  jae         _initterm+25h (43D575h)
0043D55B  mov         ecx,dword ptr [pfbegin]
0043D55E  cmp         dword ptr [ecx],0
0043D561  je          _initterm+1Ah (43D56Ah)
0043D563  mov         edx,dword ptr [pfbegin]
0043D566  mov         eax,dword ptr [edx]
0043D568  call        eax  
0043D56A  mov         ecx,dword ptr [pfbegin]
0043D56D  add         ecx,4
0043D570  mov         dword ptr [pfbegin],ecx
0043D573  jmp         _initterm+3 (43D553h)
0043D575  pop         ebp  
0043D576  ret
2009-10-28 10:06
0
雪    币: 247
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
我对汇编不熟悉
这个问题理解还没有到汇编代码的程度
期待牛人来解答
2009-10-28 10:16
0
雪    币: 178
活跃值: (159)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
IDA里面看到:
        008 push    offset __xi_z
        00C push    offset __xi_a;这个值就是pfbegin,由编译器给你定好的值
        010 call    j__initterm_e;这个值就是pfend,由编译器给你定好的值

详细的编译原理参考
http://blog.csdn.net/peteryxk/archive/2005/01/31/275564.aspx
2009-10-28 11:14
0
雪    币: 367
活跃值: (20)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
6
因为 a,b 先于g_test申明,故先初始化.
由于你的函数是类声明时包含了实现,在VC中默认此类函数为inline,其他编译器不清楚.
所幸你没有在getvalue使用成员数据.否则,行为会不确定的.因为此时g_test还没初始化.

我觉得应该是这样
2009-10-28 14:05
0
游客
登录 | 注册 方可回帖
返回
//