元始天尊 发表于 2014-10-13 20:16:24

重识new之三

本帖最后由 元始天尊 于 2014-10-14 21:48 编辑

一、MyClass* fPtr4 = new MyClass;生成的汇编代码在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   , eax
.text:004184D1 C7 45 FC 03 00 00 00                  mov   , 3
.text:004184D8 83 BD 60 FE FF FF 00                  cmp   , 0
.text:004184DF 74 3A                                 jz      short loc_41851B
.text:004184E1 8B 85 60 FE FF FF                     mov   eax,
.text:004184E7 C7 00 02 00 00 00                     mov   dword ptr , 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,
.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,
.text:00418510 83 C2 04                              add   edx, 4
.text:00418513 89 95 D4 FD FF FF                     mov   , 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   , 0
.text:00418525
.text:00418525                         loc_418525:                           ; CODE XREF: _main+239j
.text:00418525 8B 85 D4 FD FF FF                     mov   eax,
.text:0041852B 89 85 54 FE FF FF                     mov   , eax
.text:00418531 C7 45 FC FF FF FF FF                  mov   , 0FFFFFFFFh
.text:00418538 8B 8D 54 FE FF FF                     mov   ecx,
.text:0041853E 89 4D B8                              mov   , ecx


先进行整体分析,该代码段先调用了new[],如果成功分配内存,则调用数组构造迭代器vector_constructor_iterator对每个对象进行构造
void* base=new[](sizeof(int)+sizeof(MyClass));//起始4字节存储要初始化的对象个数,剩余空间为对象占用内存
if(base)
{
*(int*)base=2;//2个对象
vector_construtor_iterator((MyClass*)((char*)base+4),sizeof(MyClass),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 ptr8
.text:004156E0                         size            = dword ptr0Ch
.text:004156E0                         count         = dword ptr10h
.text:004156E0                         pCtor         = dword ptr14h
.text:004156E0                         pDtor         = dword ptr18h
.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   , eax
.text:00415704 33 C5                                 xor   eax, ebp
.text:00415706 50                                    push    eax
.text:00415707 8D 45 F0                              lea   eax,
.text:0041570A 64 A3 00 00 00 00                     mov   large fs:0, eax
.text:00415710 C7 45 E0 00 00 00 00                  mov   , 0
.text:00415717 C7 45 FC 00 00 00 00                  mov   , 0
.text:0041571E C7 45 E4 00 00 00 00                  mov   , 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,
.text:0041572A 83 C0 01                              add   eax, 1
.text:0041572D 89 45 E4                              mov   , 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,
.text:00415733 3B 4D 10                              cmp   ecx,
.text:00415736 7D 11                                 jge   short loc_415749
.text:00415738 8B 4D 08                              mov   ecx,
.text:0041573B FF 55 14                              call   
.text:0041573E 8B 55 08                              mov   edx,
.text:00415741 03 55 0C                              add   edx,
.text:00415744 89 55 08                              mov   , 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   , 1
.text:00415750 C7 45 FC FE FF FF FF                  mov   , 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   , 0 ; Finally handler 0 for function 4156E0
.text:00415762 75 15                                 jnz   short $LN10
.text:00415764 8B 45 18                              mov   eax,
.text:00415767 50                                    push    eax             ; pDtor
.text:00415768 8B 4D E4                              mov   ecx,
.text:0041576B 51                                    push    ecx             ; count
.text:0041576C 8B 55 0C                              mov   edx,
.text:0041576F 52                                    push    edx             ; size
.text:00415770 8B 45 08                              mov   eax,
.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,
.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   , eax
.text:00415904 33 C5                                 xor   eax, ebp
.text:00415906 50                                    push    eax
.text:00415907 8D 45 F0                              lea   eax,
.text:0041590A 64 A3 00 00 00 00                     mov   large fs:0, eax
.text:00415910 89 65 E8                              mov   , esp
.text:00415913 C7 45 FC 00 00 00 00                  mov   , 0
.text:0041591A
.text:0041591A                         loc_41591A:                           ; CODE XREF: __ArrayUnwind(void *,uint,int,void (*)(void *))+54j
.text:0041591A 8B 45 10                              mov   eax,
.text:0041591D 83 E8 01                              sub   eax, 1
.text:00415920 89 45 10                              mov   , eax
.text:00415923 78 11                                 js      short loc_415936
.text:00415925 8B 4D 08                              mov   ecx,
.text:00415928 2B 4D 0C                              sub   ecx,
.text:0041592B 89 4D 08                              mov   , ecx
.text:0041592E 8B 4D 08                              mov   ecx,
.text:00415931 FF 55 14                              call   
.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   , 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, ; 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, ; Exception handler 0 for function 4158E0
.text:0041594F C7 45 FC FE FF FF FF                  mov   , 0FFFFFFFEh
.text:00415956
.text:00415956                         loc_415956:                           ; CODE XREF: __ArrayUnwind(void *,uint,int,void (*)(void *))+5Dj
.text:00415956 8B 4D F0                              mov   ecx,
.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*))
{//第对象由于没有构造成功,因此从个对象开始析构
    __try
    {
      while(count--)
      {
         objs--;
         objs->pDtor();
      }
    }
    __except(terminate(),0)//如果析构发生异常,则终止程序
    {
      return;
    }
}


下面来看第一种形式delete的情况,
delete []fPtr4;

.text:00418541 8B 45 B8                              mov   eax,
.text:00418544 89 85 78 FE FF FF                     mov   , eax
.text:0041854A 8B 8D 78 FE FF FF                     mov   ecx,
.text:00418550 89 8D 6C FE FF FF                     mov   , ecx
.text:00418556 83 BD 6C FE FF FF 00                  cmp   , 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, ; 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   , 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   , 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,
.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   , ecx
.text:004133F3 8B 45 08                              mov   eax,
.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,
.text:00413403 8B 48 FC                              mov   ecx,
.text:00413406 51                                    push    ecx             ; count
.text:00413407 6A 04                                 push    4               ; size
.text:00413409 8B 55 F8                              mov   edx,
.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,
.text:00413415 83 E0 01                              and   eax, 1
.text:00413418 74 0F                                 jz      short loc_413429
.text:0041341A 8B 45 F8                              mov   eax,
.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,
.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, ; this
.text:00413434 E8 EA DB FF FF                        call    j_??1MyClass@@QAE@XZ ; MyClass::~MyClass(void)
.text:00413439 8B 45 08                              mov   eax,
.text:0041343C 83 E0 01                              and   eax, 1
.text:0041343F 74 0C                                 jz      short loc_41344D
.text:00413441 8B 45 F8                              mov   eax,
.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,
.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个二进制位为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   , eax
.text:004157E4 33 C5                                 xor   eax, ebp
.text:004157E6 50                                    push    eax
.text:004157E7 8D 45 F0                              lea   eax,
.text:004157EA 64 A3 00 00 00 00                     mov   large fs:0, eax
.text:004157F0 C7 45 E4 00 00 00 00                  mov   , 0
.text:004157F7 8B 45 0C                              mov   eax,
.text:004157FA 0F AF 45 10                           imul    eax,
.text:004157FE 03 45 08                              add   eax,
.text:00415801 89 45 08                              mov   , eax
.text:00415804 C7 45 FC 00 00 00 00                  mov   , 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,
.text:0041580E 83 E9 01                              sub   ecx, 1
.text:00415811 89 4D 10                              mov   , ecx
.text:00415814 78 11                                 js      short loc_415827
.text:00415816 8B 55 08                              mov   edx,
.text:00415819 2B 55 0C                              sub   edx,
.text:0041581C 89 55 08                              mov   , edx
.text:0041581F 8B 4D 08                              mov   ecx,
.text:00415822 FF 55 14                              call   
.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   , 1
.text:0041582E C7 45 FC FE FF FF FF                  mov   , 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   , 0 ; Finally handler 0 for function 4157C0
.text:00415840 75 15                                 jnz   short $LN9_0
.text:00415842 8B 45 14                              mov   eax,
.text:00415845 50                                    push    eax             ; pDtor
.text:00415846 8B 4D 10                              mov   ecx,
.text:00415849 51                                    push    ecx             ; count
.text:0041584A 8B 55 0C                              mov   edx,
.text:0041584D 52                                    push    edx             ; size
.text:0041584E 8B 45 08                              mov   eax,
.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,
.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;
单步转到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;
MyClass* fPtr6 = new ( &x2 ) MyClass;


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

0xAA55 发表于 2014-10-13 20:27:04

我注意到你的排版比起以前的帖子好多了
页: [1]
查看完整版本: 重识new之三