<<深入理解C++内存对象模型>>这本书里面说到,编译器为形如struct s;
s* ps=new s[3];生成的代码相当于一个循环。但是我看它的反汇编没有看懂,因为我觉得反汇编的实现应该比这个伪代码复杂。
书上说伪代码是像这样的: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一个函数。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数组的反汇编代码是: 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的这个函数没有源代码,只有反汇编语句:--- 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指令太多了,不像是只做了一个循环的样子。还做了什么?
s* ps=new s[3];生成的代码相当于一个循环。但是我看它的反汇编没有看懂,因为我觉得反汇编的实现应该比这个伪代码复杂。
书上说伪代码是像这样的: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一个函数。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数组的反汇编代码是: 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的这个函数没有源代码,只有反汇编语句:--- 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 是要构造的对象的数量。