UID 2
精华
积分 7736
威望 点
宅币 个
贡献 次
宅之契约 份
最后登录 1970-1-1
在线时间 小时
本帖最后由 元始天尊 于 2014-10-14 21:48 编辑
一、MyClass* fPtr4 = new MyClass[2];生成的汇编代码在ida中如下(这里简单说下定位方法,由于是debug版因此现在vs调试中的查看反汇编找到这条语句对应指令序列,之后再ida中找到这个序列,使用ida的好处就是用它强大的符号解析功能):
.text:004184C1 6A 0C push 0Ch ; count
.text:004184C3 E8 D2 8C FF FF call j_??_U@YAPAXI@Z ; operator new[](uint)
.text:004184C8 83 C4 04 add esp, 4
.text:004184CB 89 85 60 FE FF FF mov [ebp+var_1A0], eax
.text:004184D1 C7 45 FC 03 00 00 00 mov [ebp+var_4], 3
.text:004184D8 83 BD 60 FE FF FF 00 cmp [ebp+var_1A0], 0
.text:004184DF 74 3A jz short loc_41851B
.text:004184E1 8B 85 60 FE FF FF mov eax, [ebp+var_1A0]
.text:004184E7 C7 00 02 00 00 00 mov dword ptr [eax], 2
.text:004184ED 68 23 10 41 00 push offset j_??1MyClass@@QAE@XZ ; pDtor
.text:004184F2 68 BE 10 41 00 push offset j_??0MyClass@@QAE@XZ ; pCtor
.text:004184F7 6A 02 push 2 ; count
.text:004184F9 6A 04 push 4 ; size
.text:004184FB 8B 8D 60 FE FF FF mov ecx, [ebp+var_1A0]
.text:00418501 83 C1 04 add ecx, 4
.text:00418504 51 push ecx ; ptr
.text:00418505 E8 0C 8E FF FF call j_??_L@YGXPAXIHP6EX0@Z1@Z ; `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *))
.text:0041850A ; ---------------------------------------------------------------------------
.text:0041850A 8B 95 60 FE FF FF mov edx, [ebp+var_1A0]
.text:00418510 83 C2 04 add edx, 4
.text:00418513 89 95 D4 FD FF FF mov [ebp+var_22C], edx
.text:00418519 EB 0A jmp short loc_418525
.text:0041851B ; ---------------------------------------------------------------------------
.text:0041851B
.text:0041851B loc_41851B: ; CODE XREF: _main+1FFj
.text:0041851B C7 85 D4 FD FF FF 00 00+ mov [ebp+var_22C], 0
.text:00418525
.text:00418525 loc_418525: ; CODE XREF: _main+239j
.text:00418525 8B 85 D4 FD FF FF mov eax, [ebp+var_22C]
.text:0041852B 89 85 54 FE FF FF mov [ebp+var_1AC], eax
.text:00418531 C7 45 FC FF FF FF FF mov [ebp+var_4], 0FFFFFFFFh
.text:00418538 8B 8D 54 FE FF FF mov ecx, [ebp+var_1AC]
.text:0041853E 89 4D B8 mov [ebp+fPtr4], ecx
复制代码
先进行整体分析,该代码段先调用了new[],如果成功分配内存,则调用数组构造迭代器vector_constructor_iterator对每个对象进行构造
void* base=new[](sizeof(int)+sizeof(MyClass[2]));//起始4字节存储要初始化的对象个数,剩余空间为对象占用内存
if(base)
{
*(int*)base=2;//2个对象
vector_construtor_iterator((MyClass*)((char*)base+4),sizeof(MyClass[2]),2,&MyClass::MyClass,&MyClass::~MyClass);
}
vector_constructor_iterator对应代码为:
.text:004156E0 ; void __stdcall `eh vector constructor iterator'(void *ptr, unsigned int size, int count, void (__thiscall *pCtor)(void *), void (__thiscall *pDtor)(void *))
.text:004156E0 ??_L@YGXPAXIHP6EX0@Z1@Z proc near ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *))j
.text:004156E0
.text:004156E0 success = dword ptr -20h
.text:004156E0 i = dword ptr -1Ch
.text:004156E0 ms_exc = CPPEH_RECORD ptr -18h
.text:004156E0 ptr = dword ptr 8
.text:004156E0 size = dword ptr 0Ch
.text:004156E0 count = dword ptr 10h
.text:004156E0 pCtor = dword ptr 14h
.text:004156E0 pDtor = dword ptr 18h
.text:004156E0
.text:004156E0 55 push ebp
.text:004156E1 8B EC mov ebp, esp
.text:004156E3 6A FE push 0FFFFFFFEh
.text:004156E5 68 A0 F9 41 00 push offset stru_41F9A0
.text:004156EA 68 31 11 41 00 push offset j___except_handler4
.text:004156EF 64 A1 00 00 00 00 mov eax, large fs:0
.text:004156F5 50 push eax
.text:004156F6 83 C4 F0 add esp, 0FFFFFFF0h
.text:004156F9 53 push ebx
.text:004156FA 56 push esi
.text:004156FB 57 push edi
.text:004156FC A1 E0 00 42 00 mov eax, ___security_cookie
.text:00415701 31 45 F8 xor [ebp+ms_exc.registration.ScopeTable], eax
.text:00415704 33 C5 xor eax, ebp
.text:00415706 50 push eax
.text:00415707 8D 45 F0 lea eax, [ebp+ms_exc.registration]
.text:0041570A 64 A3 00 00 00 00 mov large fs:0, eax
.text:00415710 C7 45 E0 00 00 00 00 mov [ebp+success], 0
.text:00415717 C7 45 FC 00 00 00 00 mov [ebp+ms_exc.registration.TryLevel], 0
.text:0041571E C7 45 E4 00 00 00 00 mov [ebp+i], 0
.text:00415725 EB 09 jmp short loc_415730
.text:00415727 ; ---------------------------------------------------------------------------
.text:00415727
.text:00415727 loc_415727: ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *))+67j
.text:00415727 8B 45 E4 mov eax, [ebp+i]
.text:0041572A 83 C0 01 add eax, 1
.text:0041572D 89 45 E4 mov [ebp+i], eax
.text:00415730
.text:00415730 loc_415730: ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *))+45j
.text:00415730 8B 4D E4 mov ecx, [ebp+i]
.text:00415733 3B 4D 10 cmp ecx, [ebp+count]
.text:00415736 7D 11 jge short loc_415749
.text:00415738 8B 4D 08 mov ecx, [ebp+ptr]
.text:0041573B FF 55 14 call [ebp+pCtor]
.text:0041573E 8B 55 08 mov edx, [ebp+ptr]
.text:00415741 03 55 0C add edx, [ebp+size]
.text:00415744 89 55 08 mov [ebp+ptr], edx
.text:00415747 EB DE jmp short loc_415727
.text:00415749 ; ---------------------------------------------------------------------------
.text:00415749
.text:00415749 loc_415749: ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *))+56j
.text:00415749 C7 45 E0 01 00 00 00 mov [ebp+success], 1
.text:00415750 C7 45 FC FE FF FF FF mov [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
.text:00415757 E8 02 00 00 00 call $LN9 ; Finally handler 0 for function 4156E0
.text:0041575C ; ---------------------------------------------------------------------------
.text:0041575C
.text:0041575C loc_41575C: ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *)):$LN10j
.text:0041575C EB 1C jmp short $LN12
.text:0041575E ; ---------------------------------------------------------------------------
.text:0041575E
.text:0041575E $LN9: ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *))+77j
.text:0041575E ; DATA XREF: .rdata:stru_41F9A0o
.text:0041575E 83 7D E0 00 cmp [ebp+success], 0 ; Finally handler 0 for function 4156E0
.text:00415762 75 15 jnz short $LN10
.text:00415764 8B 45 18 mov eax, [ebp+pDtor]
.text:00415767 50 push eax ; pDtor
.text:00415768 8B 4D E4 mov ecx, [ebp+i]
.text:0041576B 51 push ecx ; count
.text:0041576C 8B 55 0C mov edx, [ebp+size]
.text:0041576F 52 push edx ; size
.text:00415770 8B 45 08 mov eax, [ebp+ptr]
.text:00415773 50 push eax ; ptr
.text:00415774 E8 E2 BC FF FF call j_?__ArrayUnwind@@YGXPAXIHP6EX0@Z@Z ; __ArrayUnwind(void *,uint,int,void (*)(void *))
.text:00415779
.text:00415779 $LN10: ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *))+82j
.text:00415779 C3 retn
.text:0041577A ; ---------------------------------------------------------------------------
.text:0041577A
.text:0041577A $LN12: ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *)):loc_41575Cj
.text:0041577A 8B 4D F0 mov ecx, [ebp+ms_exc.registration.Next]
.text:0041577D 64 89 0D 00 00 00 00 mov large fs:0, ecx
.text:00415784 59 pop ecx
.text:00415785 5F pop edi
.text:00415786 5E pop esi
.text:00415787 5B pop ebx
.text:00415788 8B E5 mov esp, ebp
.text:0041578A 5D pop ebp
.text:0041578B C2 14 00 retn 14h
.text:0041578B ??_L@YGXPAXIHP6EX0@Z1@Z endp
复制代码
翻译成C++语言为(想知道怎么翻译的,敬请期待我将要写的逆向书):
void __stdcall vector_constructor_iterator(MyClass *objs, unsigned int size, int count, void (__thiscall *pCtor)(void *), void (__thiscall *pDtor)(void *))
{
int i=0;
__try
{
for(;i<count;i++,objs++)
{
objs->pCtor();//用构造函数构造
}
}
__except(1)
{
__ArrayUnwind(objs,size,i,pDtor);//如果某个构造函数产生异常,则进行栈解退,用到析构函数
}
}
复制代码
栈解退,这里引用C++ Primer Plus的解释:
“现在假设函数由于出现异常而终止(而不是由于返回),则程序也将释放栈中的内存,但不会在释放栈的第一个返回地址后停止,而是继续释放栈,直到找到一个位于try块中的返回地址,随后控制权将转到块尾的异常处理程序,而不会函数调用后面的第一条语句。这个过程称为栈解退,引发机制的一个非常重要的特性是,和函数返回一样,对于栈中的自动类对象,而throw语句则处理try块和throw之间的整个函数调用徐丽放在栈中的对象。如果没有栈解退这种特性,则引发异常后,对于中间函数调用放在栈中的自动类对象,其析构函数将不会被调用。”
unwind就是解退的意思,现在来查看__ArrayUnwind的源码,根据函数名可知该函数用于对象数组解退:
.text:004158E0 55 push ebp
.text:004158E1 8B EC mov ebp, esp
.text:004158E3 6A FE push 0FFFFFFFEh
.text:004158E5 68 E0 F9 41 00 push offset stru_41F9E0
.text:004158EA 68 31 11 41 00 push offset j___except_handler4
.text:004158EF 64 A1 00 00 00 00 mov eax, large fs:0
.text:004158F5 50 push eax
.text:004158F6 83 EC 08 sub esp, 8
.text:004158F9 53 push ebx
.text:004158FA 56 push esi
.text:004158FB 57 push edi
.text:004158FC A1 E0 00 42 00 mov eax, ___security_cookie
.text:00415901 31 45 F8 xor [ebp+ms_exc.registration.ScopeTable], eax
.text:00415904 33 C5 xor eax, ebp
.text:00415906 50 push eax
.text:00415907 8D 45 F0 lea eax, [ebp+ms_exc.registration]
.text:0041590A 64 A3 00 00 00 00 mov large fs:0, eax
.text:00415910 89 65 E8 mov [ebp+ms_exc.old_esp], esp
.text:00415913 C7 45 FC 00 00 00 00 mov [ebp+ms_exc.registration.TryLevel], 0
.text:0041591A
.text:0041591A loc_41591A: ; CODE XREF: __ArrayUnwind(void *,uint,int,void (*)(void *))+54j
.text:0041591A 8B 45 10 mov eax, [ebp+count]
.text:0041591D 83 E8 01 sub eax, 1
.text:00415920 89 45 10 mov [ebp+count], eax
.text:00415923 78 11 js short loc_415936
.text:00415925 8B 4D 08 mov ecx, [ebp+ptr]
.text:00415928 2B 4D 0C sub ecx, [ebp+size]
.text:0041592B 89 4D 08 mov [ebp+ptr], ecx
.text:0041592E 8B 4D 08 mov ecx, [ebp+ptr]
.text:00415931 FF 55 14 call [ebp+pDtor]
.text:00415934 EB E4 jmp short loc_41591A
.text:00415936 ; ---------------------------------------------------------------------------
.text:00415936
.text:00415936 loc_415936: ; CODE XREF: __ArrayUnwind(void *,uint,int,void (*)(void *))+43j
.text:00415936 C7 45 FC FE FF FF FF mov [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
.text:0041593D EB 17 jmp short loc_415956
.text:0041593F ; ---------------------------------------------------------------------------
.text:0041593F
.text:0041593F $LN7: ; DATA XREF: .rdata:stru_41F9E0o
.text:0041593F 8B 55 EC mov edx, [ebp+ms_exc.exc_ptr] ; Exception filter 0 for function 4158E0
.text:00415942 52 push edx ; pExPtrs
.text:00415943 E8 58 FF FF FF call ArrayUnwindFilter
.text:00415948 83 C4 04 add esp, 4
.text:0041594B
.text:0041594B $LN9_1:
.text:0041594B C3 retn
.text:0041594C ; ---------------------------------------------------------------------------
.text:0041594C
.text:0041594C $LN8_0: ; DATA XREF: .rdata:stru_41F9E0o
.text:0041594C 8B 65 E8 mov esp, [ebp+ms_exc.old_esp] ; Exception handler 0 for function 4158E0
.text:0041594F C7 45 FC FE FF FF FF mov [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
.text:00415956
.text:00415956 loc_415956: ; CODE XREF: __ArrayUnwind(void *,uint,int,void (*)(void *))+5Dj
.text:00415956 8B 4D F0 mov ecx, [ebp+ms_exc.registration.Next]
.text:00415959 64 89 0D 00 00 00 00 mov large fs:0, ecx
.text:00415960 59 pop ecx
.text:00415961 5F pop edi
.text:00415962 5E pop esi
.text:00415963 5B pop ebx
.text:00415964 8B E5 mov esp, ebp
.text:00415966 5D pop ebp
.text:00415967 C2 10 00 retn 10h
复制代码
翻译之后的C++代码为:
void __stdcall __ArrayUnwind(MyClass* objs,unsigned size,int count,void (__thiscall *pDtor)(void*))
{//第[count]对象由于没有构造成功,因此从[count-1]个对象开始析构
__try
{
while(count--)
{
objs--;
objs->pDtor();
}
}
__except(terminate(),0)//如果析构发生异常,则终止程序
{
return;
}
}
复制代码
下面来看第一种形式delete的情况,
delete []fPtr4;
.text:00418541 8B 45 B8 mov eax, [ebp+fPtr4]
.text:00418544 89 85 78 FE FF FF mov [ebp+var_188], eax
.text:0041854A 8B 8D 78 FE FF FF mov ecx, [ebp+var_188]
.text:00418550 89 8D 6C FE FF FF mov [ebp+var_194], ecx
.text:00418556 83 BD 6C FE FF FF 00 cmp [ebp+var_194], 0
.text:0041855D 74 15 jz short loc_418574//如果之前new成功,则往下执行
.text:0041855F 6A 03 push 3 ; unsigned int
.text:00418561 8B 8D 6C FE FF FF mov ecx, [ebp+var_194] ; this
.text:00418567 E8 1E 8D FF FF call j_??_EMyClass@@QAEPAXI@Z ; MyClass::`vector deleting destructor'(uint)
.text:0041856C 89 85 D4 FD FF FF mov [ebp+var_22C], eax
.text:00418572 EB 0A jmp short loc_41857E
.text:00418574 ; ---------------------------------------------------------------------------
.text:00418574
.text:00418574 loc_418574: ; CODE XREF: _main+27Dj
.text:00418574 C7 85 D4 FD FF FF 00 00+ mov [ebp+var_22C], 0
复制代码
可见vector_deleting_destructor是用来析构对象数组的,原型为void* __thiscall MyClass::vector_deleting_destructor(usigned int flag);,该函数是编译器内部为MyClass类加的成员函数
flag含义未知,所以需要分析该函数源码:
.text:004133D0 55 push ebp
.text:004133D1 8B EC mov ebp, esp
.text:004133D3 81 EC CC 00 00 00 sub esp, 0CCh
.text:004133D9 53 push ebx
.text:004133DA 56 push esi
.text:004133DB 57 push edi
.text:004133DC 51 push ecx
.text:004133DD 8D BD 34 FF FF FF lea edi, [ebp+var_CC]
.text:004133E3 B9 33 00 00 00 mov ecx, 33h
.text:004133E8 B8 CC CC CC CC mov eax, 0CCCCCCCCh
.text:004133ED F3 AB rep stosd
.text:004133EF 59 pop ecx
.text:004133F0 89 4D F8 mov [ebp+this], ecx
.text:004133F3 8B 45 08 mov eax, [ebp+arg_0]
.text:004133F6 83 E0 02 and eax, 2
.text:004133F9 74 36 jz short loc_413431
.text:004133FB 68 23 10 41 00 push offset j_??1MyClass@@QAE@XZ ; pDtor
.text:00413400 8B 45 F8 mov eax, [ebp+this]
.text:00413403 8B 48 FC mov ecx, [eax-4]
.text:00413406 51 push ecx ; count
.text:00413407 6A 04 push 4 ; size
.text:00413409 8B 55 F8 mov edx, [ebp+this]
.text:0041340C 52 push edx ; ptr
.text:0041340D E8 9E E0 FF FF call j_??_M@YGXPAXIHP6EX0@Z@Z ; `eh vector destructor iterator'(void *,uint,int,void (*)(void *))
.text:00413412 ; ---------------------------------------------------------------------------
.text:00413412 8B 45 08 mov eax, [ebp+arg_0]
.text:00413415 83 E0 01 and eax, 1
.text:00413418 74 0F jz short loc_413429
.text:0041341A 8B 45 F8 mov eax, [ebp+this]
.text:0041341D 83 E8 04 sub eax, 4
.text:00413420 50 push eax ; void *
.text:00413421 E8 39 DC FF FF call j_??_V@YAXPAX@Z_0 ; operator delete[](void *)
.text:00413426 83 C4 04 add esp, 4
.text:00413429
.text:00413429 loc_413429: ; CODE XREF: MyClass::`vector deleting destructor'(uint)+48j
.text:00413429 8B 45 F8 mov eax, [ebp+this]
.text:0041342C 83 E8 04 sub eax, 4
.text:0041342F EB 1F jmp short loc_413450
.text:00413431 ; ---------------------------------------------------------------------------
.text:00413431
.text:00413431 loc_413431: ; CODE XREF: MyClass::`vector deleting destructor'(uint)+29j
.text:00413431 8B 4D F8 mov ecx, [ebp+this] ; this
.text:00413434 E8 EA DB FF FF call j_??1MyClass@@QAE@XZ ; MyClass::~MyClass(void)
.text:00413439 8B 45 08 mov eax, [ebp+arg_0]
.text:0041343C 83 E0 01 and eax, 1
.text:0041343F 74 0C jz short loc_41344D
.text:00413441 8B 45 F8 mov eax, [ebp+this]
.text:00413444 50 push eax ; void *
.text:00413445 E8 0A DD FF FF call j_??3@YAXPAX@Z_0 ; operator delete(void *)
.text:0041344A 83 C4 04 add esp, 4
.text:0041344D
.text:0041344D loc_41344D: ; CODE XREF: MyClass::`vector deleting destructor'(uint)+6Fj
.text:0041344D 8B 45 F8 mov eax, [ebp+this]
.text:00413450
.text:00413450 loc_413450: ; CODE XREF: MyClass::`vector deleting destructor'(uint)+5Fj
.text:00413450 5F pop edi
.text:00413451 5E pop esi
.text:00413452 5B pop ebx
.text:00413453 81 C4 CC 00 00 00 add esp, 0CCh
.text:00413459 3B EC cmp ebp, esp
.text:0041345B E8 FC DE FF FF call j___RTC_CheckEsp
.text:00413460 8B E5 mov esp, ebp
.text:00413462 5D pop ebp
.text:00413463 C2 04 00 retn 4
复制代码
翻译成C++代码如下:
void* __thiscall MyClass::vector_deleting_destructor(usigned int flag)
{
if(flag&2)//由于push的是3,因此这里成立
{
vector_destructor_iterator(this,sizeof(MyClass),*(int*)((char*)this-4),MyClass::~MyClass);
if(flag&1))//由于push的是3,因此这里成立
{
delete[]((char*)this-4);
}
}
else
{
this->~MyClass();
if(flag&1)
{
delete(this);
}
}
}
复制代码
仅从以上代码可以分析出以下几点:
1.this-4这个地址为之前new[]()成功分配所返回值,可以将其看成sizeof(int)+sizeof(MyClass[2])大小的结构体,第一个成员为对象个数。
2.该函数对数组和非数组进行了分别处理,可以分析出第2个二进制位为1时,是析构对象数组,为0时是析构普通对象。而第1个二进制位是规定是否释放内存,可以想象如果这里是定位new,那么这里是不应该释放的。
3.vector_destructor_iterator起实际析构作用原型
void __stdcall vector_destructor_iterator(MyClass *objs, unsigned int size, int count, void (__thiscall *pDtor)(void *));
下面来看该函数代码:
.text:004157C0 55 push ebp
.text:004157C1 8B EC mov ebp, esp
.text:004157C3 6A FE push 0FFFFFFFEh
.text:004157C5 68 C0 F9 41 00 push offset stru_41F9C0
.text:004157CA 68 31 11 41 00 push offset j___except_handler4
.text:004157CF 64 A1 00 00 00 00 mov eax, large fs:0
.text:004157D5 50 push eax
.text:004157D6 83 C4 F4 add esp, 0FFFFFFF4h
.text:004157D9 53 push ebx
.text:004157DA 56 push esi
.text:004157DB 57 push edi
.text:004157DC A1 E0 00 42 00 mov eax, ___security_cookie
.text:004157E1 31 45 F8 xor [ebp+ms_exc.registration.ScopeTable], eax
.text:004157E4 33 C5 xor eax, ebp
.text:004157E6 50 push eax
.text:004157E7 8D 45 F0 lea eax, [ebp+ms_exc.registration]
.text:004157EA 64 A3 00 00 00 00 mov large fs:0, eax
.text:004157F0 C7 45 E4 00 00 00 00 mov [ebp+success], 0
.text:004157F7 8B 45 0C mov eax, [ebp+size]
.text:004157FA 0F AF 45 10 imul eax, [ebp+count]
.text:004157FE 03 45 08 add eax, [ebp+ptr]
.text:00415801 89 45 08 mov [ebp+ptr], eax
.text:00415804 C7 45 FC 00 00 00 00 mov [ebp+ms_exc.registration.TryLevel], 0
.text:0041580B
.text:0041580B loc_41580B: ; CODE XREF: `eh vector destructor iterator'(void *,uint,int,void (*)(void *))+65j
.text:0041580B 8B 4D 10 mov ecx, [ebp+count]
.text:0041580E 83 E9 01 sub ecx, 1
.text:00415811 89 4D 10 mov [ebp+count], ecx
.text:00415814 78 11 js short loc_415827
.text:00415816 8B 55 08 mov edx, [ebp+ptr]
.text:00415819 2B 55 0C sub edx, [ebp+size]
.text:0041581C 89 55 08 mov [ebp+ptr], edx
.text:0041581F 8B 4D 08 mov ecx, [ebp+ptr]
.text:00415822 FF 55 14 call [ebp+pDtor]
.text:00415825 EB E4 jmp short loc_41580B
.text:00415827 ; ---------------------------------------------------------------------------
.text:00415827
.text:00415827 loc_415827: ; CODE XREF: `eh vector destructor iterator'(void *,uint,int,void (*)(void *))+54j
.text:00415827 C7 45 E4 01 00 00 00 mov [ebp+success], 1
.text:0041582E C7 45 FC FE FF FF FF mov [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
.text:00415835 E8 02 00 00 00 call $LN8 ; Finally handler 0 for function 4157C0
.text:0041583A ; ---------------------------------------------------------------------------
.text:0041583A
.text:0041583A loc_41583A: ; CODE XREF: `eh vector destructor iterator'(void *,uint,int,void (*)(void *)):$LN9_0j
.text:0041583A EB 1C jmp short $LN11
.text:0041583C ; ---------------------------------------------------------------------------
.text:0041583C
.text:0041583C $LN8: ; CODE XREF: `eh vector destructor iterator'(void *,uint,int,void (*)(void *))+75j
.text:0041583C ; DATA XREF: .rdata:stru_41F9C0o
.text:0041583C 83 7D E4 00 cmp [ebp+success], 0 ; Finally handler 0 for function 4157C0
.text:00415840 75 15 jnz short $LN9_0
.text:00415842 8B 45 14 mov eax, [ebp+pDtor]
.text:00415845 50 push eax ; pDtor
.text:00415846 8B 4D 10 mov ecx, [ebp+count]
.text:00415849 51 push ecx ; count
.text:0041584A 8B 55 0C mov edx, [ebp+size]
.text:0041584D 52 push edx ; size
.text:0041584E 8B 45 08 mov eax, [ebp+ptr]
.text:00415851 50 push eax ; ptr
.text:00415852 E8 04 BC FF FF call j_?__ArrayUnwind@@YGXPAXIHP6EX0@Z@Z ; __ArrayUnwind(void *,uint,int,void (*)(void *))
.text:00415857
.text:00415857 $LN9_0: ; CODE XREF: `eh vector destructor iterator'(void *,uint,int,void (*)(void *))+80j
.text:00415857 C3 retn
.text:00415858 ; ---------------------------------------------------------------------------
.text:00415858
.text:00415858 $LN11: ; CODE XREF: `eh vector destructor iterator'(void *,uint,int,void (*)(void *)):loc_41583Aj
.text:00415858 8B 4D F0 mov ecx, [ebp+ms_exc.registration.Next]
.text:0041585B 64 89 0D 00 00 00 00 mov large fs:0, ecx
.text:00415862 59 pop ecx
.text:00415863 5F pop edi
.text:00415864 5E pop esi
.text:00415865 5B pop ebx
.text:00415866 8B E5 mov esp, ebp
.text:00415868 5D pop ebp
.text:00415869 C2 10 00 retn 10h
复制代码
翻译为C++语言为:
void __stdcall vector_destructor_iterator(MyClass *objs, unsigned int size, int count, void (__thiscall *pDtor)(void *))
{
int i=0;
__try
{
MyClass* last=objs+size-1;//从最后一个对象开始析构
while(count--)
{
last->pDtor();
last--;
}
}
__except(1)
{
__ArrayUnwind(objs,size,count,pDtor);//如果某个析构函数产生异常,则跳过该对象,继续析构之前的对象
}
}
复制代码
鉴于__ArrayUnwind前面已经介绍过,这里就不分析了。
如果仔细分析上一节开头给出main汇编代码,会发现只要new成功了,delete都会去执行析构,即使出现对象数组中某个对象构造失败导致已经进行析构,delete时所有元素仍会析构一次。
二、
MyClass* fPtr5 = new( nothrow ) MyClass[2];
单步转到newaopnt.cpp
void * __CRTDECL operator new[](::size_t count, const std::nothrow_t& x)
_THROW0()
{ // try to allocate count bytes for an array
return (operator new(count, x));
}
复制代码
可见调用了单对象的第二种new形式,与非数组形式类似,不再赘述
三、
char x2[2*sizeof( MyClass ) + sizeof(int)];
MyClass* fPtr6 = new ( &x2[0] ) MyClass[2];
inline void *__CRTDECL operator new[](size_t, void *_Where) _THROW0()
{ // construct array with placement at _Where
return (_Where);
}
复制代码
可见等同于对象第三种new形式,不再赘述。
下一节会讲解所有Windows应用层内存分配函数的实现,这里暂列出这些函数名:
new和delete已经分析过,就不在赘述
_alloca _malloca 栈上分配内存
calloc 分配数组
_expand 扩展已分配内存(不是先free后malloc那种)
free
malloc
realloc