读书人

编译器为new[]生成的代码,比小弟我想象

发布时间: 2012-06-05 13:54:06 作者: rapoo

编译器为new[]生成的代码,比我想象的要复杂,讨论一下!
<<深入理解C++内存对象模型>>这本书里面说到,编译器为形如

C/C++ code
struct s;s* ps=new s[3];

生成的代码相当于一个循环。但是我看它的反汇编没有看懂,因为我觉得反汇编的实现应该比这个伪代码复杂。
书上说伪代码是像这样的:
C/C++ code
void* operator new(size_t len,void* pCtor, void* pDtor){    void*p=malloc(len);    for(int i=0;i<len/sizeof(s);++i){        s* ps=*(p+i);        new(ps) s();//构造函数,放置语法    }}

我在VC10下面编release版的代码测试了一下。编译器为new s[..]生成的代码首先push了ctor和dtor,然后call一个函数。
C/C++ code
struct s{    s(){printf("ctor\n");}    ~s(){printf("dtor\n");}    int i,j;};int main(void){    int *pi=new int;    int *pj=new int[3];    s* ps=new s;    s* pt=new s[4];    return 0;}

其中,new数组的反汇编代码是:
Assembly code
    s* pt=new s[4];0138107E  push        24h  01381080  call        operator new[] (13810C5h)  01381085  add         esp,4  01381088  mov         dword ptr [ebp-10h],eax  0138108B  mov         dword ptr [ebp-4],0  01381092  test        eax,eax  01381094  je          main+83h (13810B3h)  01381096  push        offset s::~s (1381020h)  0138109B  push        offset s::s (1381000h)  013810A0  push        4  013810A2  mov         dword ptr [eax],4  013810A8  push        8  013810AA  add         eax,4  013810AD  push        eax  013810AE  call        `eh vector constructor iterator' (13810E6h)      return 0;013810B3  xor         eax,eax  


跟进去看call语句调用的地方。
反汇编窗口显示,call的这个函数没有源代码,只有反汇编语句:
Assembly code
--- No source file -------------------------013810DF  int         3  operator new:013810E0  jmp         dword ptr [__imp_operator new (13820A0h)]  `eh vector constructor iterator':013810E6  push        10h  013810E8  push        offset ___rtc_tzz+4 (13821D8h)  013810ED  call        __SEH_prolog4 (1381550h)  013810F2  xor         eax,eax  013810F4  mov         dword ptr [ebp-20h],eax  013810F7  mov         dword ptr [ebp-4],eax  013810FA  mov         dword ptr [ebp-1Ch],eax  013810FD  mov         eax,dword ptr [ebp-1Ch]  01381100  cmp         eax,dword ptr [ebp+10h]  01381103  jge         `eh vector constructor iterator'+32h (1381118h)  01381105  mov         esi,dword ptr [ebp+8]  01381108  mov         ecx,esi  0138110A  call        dword ptr [ebp+14h]  0138110D  add         esi,dword ptr [ebp+0Ch]  01381110  mov         dword ptr [ebp+8],esi  01381113  inc         dword ptr [ebp-1Ch]  01381116  jmp         `eh vector constructor iterator'+17h (13810FDh)  01381118  mov         dword ptr [ebp-20h],1  0138111F  mov         dword ptr [ebp-4],0FFFFFFFEh  01381126  call        $LN9 (1381133h)  $LN12:0138112B  call        __SEH_epilog4 (1381595h)  01381130  ret         14h  

我的问题是,像书上那样只是一个for循环的话,应该代码没有这么长啊。
这一长串的反汇编语句除了一个循环以外,还做了什么?
看起来是做了一个异常处理,如果某次构造函数失败了,就调用dtor。
但是:
(1)为什么调用了两次跳转指令,跳到eh vector constructor iterator呢?
(2)mov指令太多了,不像是只做了一个循环的样子。还做了什么?


[解决办法]
主要代码是函数
`eh vector constructor iterator'

该函数有5个参数。

s* pt=new s[4];
这句话产生的5个参数为:

1: new 返回的地址 + 4
2: 8
3: 4
4: offset s::s
5: offset s::~s

据我猜测, 8 是s结构除虚表之外的size, 4 是要构造的对象的数量。

读书人网 >VC/MFC

热点推荐