找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 4752|回复: 1

重识new之三

[复制链接]

307

主题

228

回帖

7349

积分

用户组: 真·技术宅

UID
2
精华
76
威望
291 点
宅币
5599 个
贡献
253 次
宅之契约
0 份
在线时间
949 小时
注册时间
2014-1-25
发表于 2014-10-13 20:16:24 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

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

一、MyClass* fPtr4 = new MyClass[2];生成的汇编代码在ida中如下(这里简单说下定位方法,由于是debug版因此现在vs调试中的查看反汇编找到这条语句对应指令序列,之后再ida中找到这个序列,使用ida的好处就是用它强大的符号解析功能):

  1. .text:004184C1 6A 0C                                   push    0Ch             ; count
  2. .text:004184C3 E8 D2 8C FF FF                          call    j_??_U@YAPAXI@Z ; operator new[](uint)
  3. .text:004184C8 83 C4 04                                add     esp, 4
  4. .text:004184CB 89 85 60 FE FF FF                       mov     [ebp+var_1A0], eax
  5. .text:004184D1 C7 45 FC 03 00 00 00                    mov     [ebp+var_4], 3
  6. .text:004184D8 83 BD 60 FE FF FF 00                    cmp     [ebp+var_1A0], 0
  7. .text:004184DF 74 3A                                   jz      short loc_41851B
  8. .text:004184E1 8B 85 60 FE FF FF                       mov     eax, [ebp+var_1A0]
  9. .text:004184E7 C7 00 02 00 00 00                       mov     dword ptr [eax], 2
  10. .text:004184ED 68 23 10 41 00                          push    offset j_??1MyClass@@QAE@XZ ; pDtor
  11. .text:004184F2 68 BE 10 41 00                          push    offset j_??0MyClass@@QAE@XZ ; pCtor
  12. .text:004184F7 6A 02                                   push    2               ; count
  13. .text:004184F9 6A 04                                   push    4               ; size
  14. .text:004184FB 8B 8D 60 FE FF FF                       mov     ecx, [ebp+var_1A0]
  15. .text:00418501 83 C1 04                                add     ecx, 4
  16. .text:00418504 51                                      push    ecx             ; ptr
  17. .text:00418505 E8 0C 8E FF FF                          call    j_??_L@YGXPAXIHP6EX0@Z1@Z ; `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *))
  18. .text:0041850A                         ; ---------------------------------------------------------------------------
  19. .text:0041850A 8B 95 60 FE FF FF                       mov     edx, [ebp+var_1A0]
  20. .text:00418510 83 C2 04                                add     edx, 4
  21. .text:00418513 89 95 D4 FD FF FF                       mov     [ebp+var_22C], edx
  22. .text:00418519 EB 0A                                   jmp     short loc_418525
  23. .text:0041851B                         ; ---------------------------------------------------------------------------
  24. .text:0041851B
  25. .text:0041851B                         loc_41851B:                             ; CODE XREF: _main+1FFj
  26. .text:0041851B C7 85 D4 FD FF FF 00 00+                mov     [ebp+var_22C], 0
  27. .text:00418525
  28. .text:00418525                         loc_418525:                             ; CODE XREF: _main+239j
  29. .text:00418525 8B 85 D4 FD FF FF                       mov     eax, [ebp+var_22C]
  30. .text:0041852B 89 85 54 FE FF FF                       mov     [ebp+var_1AC], eax
  31. .text:00418531 C7 45 FC FF FF FF FF                    mov     [ebp+var_4], 0FFFFFFFFh
  32. .text:00418538 8B 8D 54 FE FF FF                       mov     ecx, [ebp+var_1AC]
  33. .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对应代码为:

  1. .text:004156E0                         ; void __stdcall `eh vector constructor iterator'(void *ptr, unsigned int size, int count, void (__thiscall *pCtor)(void *), void (__thiscall *pDtor)(void *))
  2. .text:004156E0                         ??_L@YGXPAXIHP6EX0@Z1@Z proc near       ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *))j
  3. .text:004156E0
  4. .text:004156E0                         success         = dword ptr -20h
  5. .text:004156E0                         i               = dword ptr -1Ch
  6. .text:004156E0                         ms_exc          = CPPEH_RECORD ptr -18h
  7. .text:004156E0                         ptr             = dword ptr  8
  8. .text:004156E0                         size            = dword ptr  0Ch
  9. .text:004156E0                         count           = dword ptr  10h
  10. .text:004156E0                         pCtor           = dword ptr  14h
  11. .text:004156E0                         pDtor           = dword ptr  18h
  12. .text:004156E0
  13. .text:004156E0 55                                      push    ebp
  14. .text:004156E1 8B EC                                   mov     ebp, esp
  15. .text:004156E3 6A FE                                   push    0FFFFFFFEh
  16. .text:004156E5 68 A0 F9 41 00                          push    offset stru_41F9A0
  17. .text:004156EA 68 31 11 41 00                          push    offset j___except_handler4
  18. .text:004156EF 64 A1 00 00 00 00                       mov     eax, large fs:0
  19. .text:004156F5 50                                      push    eax
  20. .text:004156F6 83 C4 F0                                add     esp, 0FFFFFFF0h
  21. .text:004156F9 53                                      push    ebx
  22. .text:004156FA 56                                      push    esi
  23. .text:004156FB 57                                      push    edi
  24. .text:004156FC A1 E0 00 42 00                          mov     eax, ___security_cookie
  25. .text:00415701 31 45 F8                                xor     [ebp+ms_exc.registration.ScopeTable], eax
  26. .text:00415704 33 C5                                   xor     eax, ebp
  27. .text:00415706 50                                      push    eax
  28. .text:00415707 8D 45 F0                                lea     eax, [ebp+ms_exc.registration]
  29. .text:0041570A 64 A3 00 00 00 00                       mov     large fs:0, eax
  30. .text:00415710 C7 45 E0 00 00 00 00                    mov     [ebp+success], 0
  31. .text:00415717 C7 45 FC 00 00 00 00                    mov     [ebp+ms_exc.registration.TryLevel], 0
  32. .text:0041571E C7 45 E4 00 00 00 00                    mov     [ebp+i], 0
  33. .text:00415725 EB 09                                   jmp     short loc_415730
  34. .text:00415727                         ; ---------------------------------------------------------------------------
  35. .text:00415727
  36. .text:00415727                         loc_415727:                             ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *))+67j
  37. .text:00415727 8B 45 E4                                mov     eax, [ebp+i]
  38. .text:0041572A 83 C0 01                                add     eax, 1
  39. .text:0041572D 89 45 E4                                mov     [ebp+i], eax
  40. .text:00415730
  41. .text:00415730                         loc_415730:                             ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *))+45j
  42. .text:00415730 8B 4D E4                                mov     ecx, [ebp+i]
  43. .text:00415733 3B 4D 10                                cmp     ecx, [ebp+count]
  44. .text:00415736 7D 11                                   jge     short loc_415749
  45. .text:00415738 8B 4D 08                                mov     ecx, [ebp+ptr]
  46. .text:0041573B FF 55 14                                call    [ebp+pCtor]
  47. .text:0041573E 8B 55 08                                mov     edx, [ebp+ptr]
  48. .text:00415741 03 55 0C                                add     edx, [ebp+size]
  49. .text:00415744 89 55 08                                mov     [ebp+ptr], edx
  50. .text:00415747 EB DE                                   jmp     short loc_415727
  51. .text:00415749                         ; ---------------------------------------------------------------------------
  52. .text:00415749
  53. .text:00415749                         loc_415749:                             ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *))+56j
  54. .text:00415749 C7 45 E0 01 00 00 00                    mov     [ebp+success], 1
  55. .text:00415750 C7 45 FC FE FF FF FF                    mov     [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
  56. .text:00415757 E8 02 00 00 00                          call    $LN9            ; Finally handler 0 for function 4156E0
  57. .text:0041575C                         ; ---------------------------------------------------------------------------
  58. .text:0041575C
  59. .text:0041575C                         loc_41575C:                             ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *)):$LN10j
  60. .text:0041575C EB 1C                                   jmp     short $LN12
  61. .text:0041575E                         ; ---------------------------------------------------------------------------
  62. .text:0041575E
  63. .text:0041575E                         $LN9:                                   ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *))+77j
  64. .text:0041575E                                                                 ; DATA XREF: .rdata:stru_41F9A0o
  65. .text:0041575E 83 7D E0 00                             cmp     [ebp+success], 0 ; Finally handler 0 for function 4156E0
  66. .text:00415762 75 15                                   jnz     short $LN10
  67. .text:00415764 8B 45 18                                mov     eax, [ebp+pDtor]
  68. .text:00415767 50                                      push    eax             ; pDtor
  69. .text:00415768 8B 4D E4                                mov     ecx, [ebp+i]
  70. .text:0041576B 51                                      push    ecx             ; count
  71. .text:0041576C 8B 55 0C                                mov     edx, [ebp+size]
  72. .text:0041576F 52                                      push    edx             ; size
  73. .text:00415770 8B 45 08                                mov     eax, [ebp+ptr]
  74. .text:00415773 50                                      push    eax             ; ptr
  75. .text:00415774 E8 E2 BC FF FF                          call    j_?__ArrayUnwind@@YGXPAXIHP6EX0@Z@Z ; __ArrayUnwind(void *,uint,int,void (*)(void *))
  76. .text:00415779
  77. .text:00415779                         $LN10:                                  ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *))+82j
  78. .text:00415779 C3                                      retn
  79. .text:0041577A                         ; ---------------------------------------------------------------------------
  80. .text:0041577A
  81. .text:0041577A                         $LN12:                                  ; CODE XREF: `eh vector constructor iterator'(void *,uint,int,void (*)(void *),void (*)(void *)):loc_41575Cj
  82. .text:0041577A 8B 4D F0                                mov     ecx, [ebp+ms_exc.registration.Next]
  83. .text:0041577D 64 89 0D 00 00 00 00                    mov     large fs:0, ecx
  84. .text:00415784 59                                      pop     ecx
  85. .text:00415785 5F                                      pop     edi
  86. .text:00415786 5E                                      pop     esi
  87. .text:00415787 5B                                      pop     ebx
  88. .text:00415788 8B E5                                   mov     esp, ebp
  89. .text:0041578A 5D                                      pop     ebp
  90. .text:0041578B C2 14 00                                retn    14h
  91. .text:0041578B                         ??_L@YGXPAXIHP6EX0@Z1@Z endp
复制代码


翻译成C++语言为(想知道怎么翻译的,敬请期待我将要写的逆向书):

  1. void __stdcall vector_constructor_iterator(MyClass *objs, unsigned int size, int count, void (__thiscall *pCtor)(void *), void (__thiscall *pDtor)(void *))
  2. {
  3.     int i=0;
  4.     __try
  5.     {
  6.         for(;i<count;i++,objs++)
  7.         {
  8.             objs->pCtor();//用构造函数构造
  9.         }      
  10.     }
  11.     __except(1)
  12.     {
  13.         __ArrayUnwind(objs,size,i,pDtor);//如果某个构造函数产生异常,则进行栈解退,用到析构函数
  14.     }
  15. }
复制代码


栈解退,这里引用C++ Primer Plus的解释:
“现在假设函数由于出现异常而终止(而不是由于返回),则程序也将释放栈中的内存,但不会在释放栈的第一个返回地址后停止,而是继续释放栈,直到找到一个位于try块中的返回地址,随后控制权将转到块尾的异常处理程序,而不会函数调用后面的第一条语句。这个过程称为栈解退,引发机制的一个非常重要的特性是,和函数返回一样,对于栈中的自动类对象,而throw语句则处理try块和throw之间的整个函数调用徐丽放在栈中的对象。如果没有栈解退这种特性,则引发异常后,对于中间函数调用放在栈中的自动类对象,其析构函数将不会被调用。”
unwind就是解退的意思,现在来查看__ArrayUnwind的源码,根据函数名可知该函数用于对象数组解退:

  1. .text:004158E0 55                                      push    ebp
  2. .text:004158E1 8B EC                                   mov     ebp, esp
  3. .text:004158E3 6A FE                                   push    0FFFFFFFEh
  4. .text:004158E5 68 E0 F9 41 00                          push    offset stru_41F9E0
  5. .text:004158EA 68 31 11 41 00                          push    offset j___except_handler4
  6. .text:004158EF 64 A1 00 00 00 00                       mov     eax, large fs:0
  7. .text:004158F5 50                                      push    eax
  8. .text:004158F6 83 EC 08                                sub     esp, 8
  9. .text:004158F9 53                                      push    ebx
  10. .text:004158FA 56                                      push    esi
  11. .text:004158FB 57                                      push    edi
  12. .text:004158FC A1 E0 00 42 00                          mov     eax, ___security_cookie
  13. .text:00415901 31 45 F8                                xor     [ebp+ms_exc.registration.ScopeTable], eax
  14. .text:00415904 33 C5                                   xor     eax, ebp
  15. .text:00415906 50                                      push    eax
  16. .text:00415907 8D 45 F0                                lea     eax, [ebp+ms_exc.registration]
  17. .text:0041590A 64 A3 00 00 00 00                       mov     large fs:0, eax
  18. .text:00415910 89 65 E8                                mov     [ebp+ms_exc.old_esp], esp
  19. .text:00415913 C7 45 FC 00 00 00 00                    mov     [ebp+ms_exc.registration.TryLevel], 0
  20. .text:0041591A
  21. .text:0041591A                         loc_41591A:                             ; CODE XREF: __ArrayUnwind(void *,uint,int,void (*)(void *))+54j
  22. .text:0041591A 8B 45 10                                mov     eax, [ebp+count]
  23. .text:0041591D 83 E8 01                                sub     eax, 1
  24. .text:00415920 89 45 10                                mov     [ebp+count], eax
  25. .text:00415923 78 11                                   js      short loc_415936
  26. .text:00415925 8B 4D 08                                mov     ecx, [ebp+ptr]
  27. .text:00415928 2B 4D 0C                                sub     ecx, [ebp+size]
  28. .text:0041592B 89 4D 08                                mov     [ebp+ptr], ecx
  29. .text:0041592E 8B 4D 08                                mov     ecx, [ebp+ptr]
  30. .text:00415931 FF 55 14                                call    [ebp+pDtor]
  31. .text:00415934 EB E4                                   jmp     short loc_41591A
  32. .text:00415936                         ; ---------------------------------------------------------------------------
  33. .text:00415936
  34. .text:00415936                         loc_415936:                             ; CODE XREF: __ArrayUnwind(void *,uint,int,void (*)(void *))+43j
  35. .text:00415936 C7 45 FC FE FF FF FF                    mov     [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
  36. .text:0041593D EB 17                                   jmp     short loc_415956
  37. .text:0041593F                         ; ---------------------------------------------------------------------------
  38. .text:0041593F
  39. .text:0041593F                         $LN7:                                   ; DATA XREF: .rdata:stru_41F9E0o
  40. .text:0041593F 8B 55 EC                                mov     edx, [ebp+ms_exc.exc_ptr] ; Exception filter 0 for function 4158E0
  41. .text:00415942 52                                      push    edx             ; pExPtrs
  42. .text:00415943 E8 58 FF FF FF                          call    ArrayUnwindFilter
  43. .text:00415948 83 C4 04                                add     esp, 4
  44. .text:0041594B
  45. .text:0041594B                         $LN9_1:
  46. .text:0041594B C3                                      retn
  47. .text:0041594C                         ; ---------------------------------------------------------------------------
  48. .text:0041594C
  49. .text:0041594C                         $LN8_0:                                 ; DATA XREF: .rdata:stru_41F9E0o
  50. .text:0041594C 8B 65 E8                                mov     esp, [ebp+ms_exc.old_esp] ; Exception handler 0 for function 4158E0
  51. .text:0041594F C7 45 FC FE FF FF FF                    mov     [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
  52. .text:00415956
  53. .text:00415956                         loc_415956:                             ; CODE XREF: __ArrayUnwind(void *,uint,int,void (*)(void *))+5Dj
  54. .text:00415956 8B 4D F0                                mov     ecx, [ebp+ms_exc.registration.Next]
  55. .text:00415959 64 89 0D 00 00 00 00                    mov     large fs:0, ecx
  56. .text:00415960 59                                      pop     ecx
  57. .text:00415961 5F                                      pop     edi
  58. .text:00415962 5E                                      pop     esi
  59. .text:00415963 5B                                      pop     ebx
  60. .text:00415964 8B E5                                   mov     esp, ebp
  61. .text:00415966 5D                                      pop     ebp
  62. .text:00415967 C2 10 00                                retn    10h
复制代码


翻译之后的C++代码为:

  1. void __stdcall __ArrayUnwind(MyClass* objs,unsigned size,int count,void (__thiscall *pDtor)(void*))
  2. {//第[count]对象由于没有构造成功,因此从[count-1]个对象开始析构
  3.     __try
  4.     {
  5.         while(count--)
  6.         {
  7.            objs--;
  8.            objs->pDtor();
  9.         }
  10.     }
  11.     __except(terminate(),0)//如果析构发生异常,则终止程序
  12.     {
  13.         return;
  14.     }
  15. }
复制代码


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

  1. .text:00418541 8B 45 B8                                mov     eax, [ebp+fPtr4]
  2. .text:00418544 89 85 78 FE FF FF                       mov     [ebp+var_188], eax
  3. .text:0041854A 8B 8D 78 FE FF FF                       mov     ecx, [ebp+var_188]
  4. .text:00418550 89 8D 6C FE FF FF                       mov     [ebp+var_194], ecx
  5. .text:00418556 83 BD 6C FE FF FF 00                    cmp     [ebp+var_194], 0
  6. .text:0041855D 74 15                                   jz      short loc_418574//如果之前new成功,则往下执行
  7. .text:0041855F 6A 03                                   push    3               ; unsigned int
  8. .text:00418561 8B 8D 6C FE FF FF                       mov     ecx, [ebp+var_194] ; this
  9. .text:00418567 E8 1E 8D FF FF                          call    j_??_EMyClass@@QAEPAXI@Z ; MyClass::`vector deleting destructor'(uint)
  10. .text:0041856C 89 85 D4 FD FF FF                       mov     [ebp+var_22C], eax
  11. .text:00418572 EB 0A                                   jmp     short loc_41857E
  12. .text:00418574                         ; ---------------------------------------------------------------------------
  13. .text:00418574
  14. .text:00418574                         loc_418574:                             ; CODE XREF: _main+27Dj
  15. .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含义未知,所以需要分析该函数源码:

  1. .text:004133D0 55                                      push    ebp
  2. .text:004133D1 8B EC                                   mov     ebp, esp
  3. .text:004133D3 81 EC CC 00 00 00                       sub     esp, 0CCh
  4. .text:004133D9 53                                      push    ebx
  5. .text:004133DA 56                                      push    esi
  6. .text:004133DB 57                                      push    edi
  7. .text:004133DC 51                                      push    ecx
  8. .text:004133DD 8D BD 34 FF FF FF                       lea     edi, [ebp+var_CC]
  9. .text:004133E3 B9 33 00 00 00                          mov     ecx, 33h
  10. .text:004133E8 B8 CC CC CC CC                          mov     eax, 0CCCCCCCCh
  11. .text:004133ED F3 AB                                   rep stosd
  12. .text:004133EF 59                                      pop     ecx
  13. .text:004133F0 89 4D F8                                mov     [ebp+this], ecx
  14. .text:004133F3 8B 45 08                                mov     eax, [ebp+arg_0]
  15. .text:004133F6 83 E0 02                                and     eax, 2
  16. .text:004133F9 74 36                                   jz      short loc_413431
  17. .text:004133FB 68 23 10 41 00                          push    offset j_??1MyClass@@QAE@XZ ; pDtor
  18. .text:00413400 8B 45 F8                                mov     eax, [ebp+this]
  19. .text:00413403 8B 48 FC                                mov     ecx, [eax-4]
  20. .text:00413406 51                                      push    ecx             ; count
  21. .text:00413407 6A 04                                   push    4               ; size
  22. .text:00413409 8B 55 F8                                mov     edx, [ebp+this]
  23. .text:0041340C 52                                      push    edx             ; ptr
  24. .text:0041340D E8 9E E0 FF FF                          call    j_??_M@YGXPAXIHP6EX0@Z@Z ; `eh vector destructor iterator'(void *,uint,int,void (*)(void *))
  25. .text:00413412                         ; ---------------------------------------------------------------------------
  26. .text:00413412 8B 45 08                                mov     eax, [ebp+arg_0]
  27. .text:00413415 83 E0 01                                and     eax, 1
  28. .text:00413418 74 0F                                   jz      short loc_413429
  29. .text:0041341A 8B 45 F8                                mov     eax, [ebp+this]
  30. .text:0041341D 83 E8 04                                sub     eax, 4
  31. .text:00413420 50                                      push    eax             ; void *
  32. .text:00413421 E8 39 DC FF FF                          call    j_??_V@YAXPAX@Z_0 ; operator delete[](void *)
  33. .text:00413426 83 C4 04                                add     esp, 4
  34. .text:00413429
  35. .text:00413429                         loc_413429:                             ; CODE XREF: MyClass::`vector deleting destructor'(uint)+48j
  36. .text:00413429 8B 45 F8                                mov     eax, [ebp+this]
  37. .text:0041342C 83 E8 04                                sub     eax, 4
  38. .text:0041342F EB 1F                                   jmp     short loc_413450
  39. .text:00413431                         ; ---------------------------------------------------------------------------
  40. .text:00413431
  41. .text:00413431                         loc_413431:                             ; CODE XREF: MyClass::`vector deleting destructor'(uint)+29j
  42. .text:00413431 8B 4D F8                                mov     ecx, [ebp+this] ; this
  43. .text:00413434 E8 EA DB FF FF                          call    j_??1MyClass@@QAE@XZ ; MyClass::~MyClass(void)
  44. .text:00413439 8B 45 08                                mov     eax, [ebp+arg_0]
  45. .text:0041343C 83 E0 01                                and     eax, 1
  46. .text:0041343F 74 0C                                   jz      short loc_41344D
  47. .text:00413441 8B 45 F8                                mov     eax, [ebp+this]
  48. .text:00413444 50                                      push    eax             ; void *
  49. .text:00413445 E8 0A DD FF FF                          call    j_??3@YAXPAX@Z_0 ; operator delete(void *)
  50. .text:0041344A 83 C4 04                                add     esp, 4
  51. .text:0041344D
  52. .text:0041344D                         loc_41344D:                             ; CODE XREF: MyClass::`vector deleting destructor'(uint)+6Fj
  53. .text:0041344D 8B 45 F8                                mov     eax, [ebp+this]
  54. .text:00413450
  55. .text:00413450                         loc_413450:                             ; CODE XREF: MyClass::`vector deleting destructor'(uint)+5Fj
  56. .text:00413450 5F                                      pop     edi
  57. .text:00413451 5E                                      pop     esi
  58. .text:00413452 5B                                      pop     ebx
  59. .text:00413453 81 C4 CC 00 00 00                       add     esp, 0CCh
  60. .text:00413459 3B EC                                   cmp     ebp, esp
  61. .text:0041345B E8 FC DE FF FF                          call    j___RTC_CheckEsp
  62. .text:00413460 8B E5                                   mov     esp, ebp
  63. .text:00413462 5D                                      pop     ebp
  64. .text:00413463 C2 04 00                                retn    4
复制代码

翻译成C++代码如下:

  1. void* __thiscall MyClass::vector_deleting_destructor(usigned int flag)
  2. {
  3.         if(flag&2)//由于push的是3,因此这里成立
  4.         {
  5.              vector_destructor_iterator(this,sizeof(MyClass),*(int*)((char*)this-4),MyClass::~MyClass);
  6.              if(flag&1))//由于push的是3,因此这里成立
  7.              {
  8.                  delete[]((char*)this-4);
  9.              }
  10.         }
  11.         else
  12.         {
  13.              this->~MyClass();
  14.              if(flag&1)
  15.              {
  16.                  delete(this);
  17.              }
  18.         }
  19. }
复制代码

仅从以上代码可以分析出以下几点:
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 *));

下面来看该函数代码:

  1. .text:004157C0 55                                      push    ebp
  2. .text:004157C1 8B EC                                   mov     ebp, esp
  3. .text:004157C3 6A FE                                   push    0FFFFFFFEh
  4. .text:004157C5 68 C0 F9 41 00                          push    offset stru_41F9C0
  5. .text:004157CA 68 31 11 41 00                          push    offset j___except_handler4
  6. .text:004157CF 64 A1 00 00 00 00                       mov     eax, large fs:0
  7. .text:004157D5 50                                      push    eax
  8. .text:004157D6 83 C4 F4                                add     esp, 0FFFFFFF4h
  9. .text:004157D9 53                                      push    ebx
  10. .text:004157DA 56                                      push    esi
  11. .text:004157DB 57                                      push    edi
  12. .text:004157DC A1 E0 00 42 00                          mov     eax, ___security_cookie
  13. .text:004157E1 31 45 F8                                xor     [ebp+ms_exc.registration.ScopeTable], eax
  14. .text:004157E4 33 C5                                   xor     eax, ebp
  15. .text:004157E6 50                                      push    eax
  16. .text:004157E7 8D 45 F0                                lea     eax, [ebp+ms_exc.registration]
  17. .text:004157EA 64 A3 00 00 00 00                       mov     large fs:0, eax
  18. .text:004157F0 C7 45 E4 00 00 00 00                    mov     [ebp+success], 0
  19. .text:004157F7 8B 45 0C                                mov     eax, [ebp+size]
  20. .text:004157FA 0F AF 45 10                             imul    eax, [ebp+count]
  21. .text:004157FE 03 45 08                                add     eax, [ebp+ptr]
  22. .text:00415801 89 45 08                                mov     [ebp+ptr], eax
  23. .text:00415804 C7 45 FC 00 00 00 00                    mov     [ebp+ms_exc.registration.TryLevel], 0
  24. .text:0041580B
  25. .text:0041580B                         loc_41580B:                             ; CODE XREF: `eh vector destructor iterator'(void *,uint,int,void (*)(void *))+65j
  26. .text:0041580B 8B 4D 10                                mov     ecx, [ebp+count]
  27. .text:0041580E 83 E9 01                                sub     ecx, 1
  28. .text:00415811 89 4D 10                                mov     [ebp+count], ecx
  29. .text:00415814 78 11                                   js      short loc_415827
  30. .text:00415816 8B 55 08                                mov     edx, [ebp+ptr]
  31. .text:00415819 2B 55 0C                                sub     edx, [ebp+size]
  32. .text:0041581C 89 55 08                                mov     [ebp+ptr], edx
  33. .text:0041581F 8B 4D 08                                mov     ecx, [ebp+ptr]
  34. .text:00415822 FF 55 14                                call    [ebp+pDtor]
  35. .text:00415825 EB E4                                   jmp     short loc_41580B
  36. .text:00415827                         ; ---------------------------------------------------------------------------
  37. .text:00415827
  38. .text:00415827                         loc_415827:                             ; CODE XREF: `eh vector destructor iterator'(void *,uint,int,void (*)(void *))+54j
  39. .text:00415827 C7 45 E4 01 00 00 00                    mov     [ebp+success], 1
  40. .text:0041582E C7 45 FC FE FF FF FF                    mov     [ebp+ms_exc.registration.TryLevel], 0FFFFFFFEh
  41. .text:00415835 E8 02 00 00 00                          call    $LN8            ; Finally handler 0 for function 4157C0
  42. .text:0041583A                         ; ---------------------------------------------------------------------------
  43. .text:0041583A
  44. .text:0041583A                         loc_41583A:                             ; CODE XREF: `eh vector destructor iterator'(void *,uint,int,void (*)(void *)):$LN9_0j
  45. .text:0041583A EB 1C                                   jmp     short $LN11
  46. .text:0041583C                         ; ---------------------------------------------------------------------------
  47. .text:0041583C
  48. .text:0041583C                         $LN8:                                   ; CODE XREF: `eh vector destructor iterator'(void *,uint,int,void (*)(void *))+75j
  49. .text:0041583C                                                                 ; DATA XREF: .rdata:stru_41F9C0o
  50. .text:0041583C 83 7D E4 00                             cmp     [ebp+success], 0 ; Finally handler 0 for function 4157C0
  51. .text:00415840 75 15                                   jnz     short $LN9_0
  52. .text:00415842 8B 45 14                                mov     eax, [ebp+pDtor]
  53. .text:00415845 50                                      push    eax             ; pDtor
  54. .text:00415846 8B 4D 10                                mov     ecx, [ebp+count]
  55. .text:00415849 51                                      push    ecx             ; count
  56. .text:0041584A 8B 55 0C                                mov     edx, [ebp+size]
  57. .text:0041584D 52                                      push    edx             ; size
  58. .text:0041584E 8B 45 08                                mov     eax, [ebp+ptr]
  59. .text:00415851 50                                      push    eax             ; ptr
  60. .text:00415852 E8 04 BC FF FF                          call    j_?__ArrayUnwind@@YGXPAXIHP6EX0@Z@Z ; __ArrayUnwind(void *,uint,int,void (*)(void *))
  61. .text:00415857
  62. .text:00415857                         $LN9_0:                                 ; CODE XREF: `eh vector destructor iterator'(void *,uint,int,void (*)(void *))+80j
  63. .text:00415857 C3                                      retn
  64. .text:00415858                         ; ---------------------------------------------------------------------------
  65. .text:00415858
  66. .text:00415858                         $LN11:                                  ; CODE XREF: `eh vector destructor iterator'(void *,uint,int,void (*)(void *)):loc_41583Aj
  67. .text:00415858 8B 4D F0                                mov     ecx, [ebp+ms_exc.registration.Next]
  68. .text:0041585B 64 89 0D 00 00 00 00                    mov     large fs:0, ecx
  69. .text:00415862 59                                      pop     ecx
  70. .text:00415863 5F                                      pop     edi
  71. .text:00415864 5E                                      pop     esi
  72. .text:00415865 5B                                      pop     ebx
  73. .text:00415866 8B E5                                   mov     esp, ebp
  74. .text:00415868 5D                                      pop     ebp
  75. .text:00415869 C2 10 00                                retn    10h
复制代码


翻译为C++语言为:

  1. void __stdcall vector_destructor_iterator(MyClass *objs, unsigned int size, int count, void (__thiscall *pDtor)(void *))
  2. {
  3.     int i=0;
  4.     __try
  5.     {
  6.         MyClass* last=objs+size-1;//从最后一个对象开始析构
  7.         while(count--)
  8.         {
  9.            last->pDtor();
  10.            last--;
  11.         }
  12.     }
  13.     __except(1)
  14.     {
  15.         __ArrayUnwind(objs,size,count,pDtor);//如果某个析构函数产生异常,则跳过该对象,继续析构之前的对象
  16.     }
  17. }
复制代码

鉴于__ArrayUnwind前面已经介绍过,这里就不分析了。
如果仔细分析上一节开头给出main汇编代码,会发现只要new成功了,delete都会去执行析构,即使出现对象数组中某个对象构造失败导致已经进行析构,delete时所有元素仍会析构一次。

二、
MyClass* fPtr5 = new( nothrow ) MyClass[2];
单步转到newaopnt.cpp

  1. void * __CRTDECL operator new[](::size_t count, const std::nothrow_t& x)
  2.         _THROW0()
  3.         {        // try to allocate count bytes for an array
  4.         return (operator new(count, x));
  5.         }
复制代码

可见调用了单对象的第二种new形式,与非数组形式类似,不再赘述

三、
char x2[2*sizeof( MyClass ) + sizeof(int)];
MyClass* fPtr6 = new ( &x2[0] ) MyClass[2];


  1. inline void *__CRTDECL operator new[](size_t, void *_Where) _THROW0()
  2. {        // construct array with placement at _Where
  3.         return (_Where);
  4. }
复制代码

可见等同于对象第三种new形式,不再赘述。


下一节会讲解所有Windows应用层内存分配函数的实现,这里暂列出这些函数名:
new和delete已经分析过,就不在赘述
_alloca  _malloca  栈上分配内存
calloc  分配数组
_expand  扩展已分配内存(不是先free后malloc那种)
free
malloc
realloc

回复

使用道具 举报

1112

主题

1653

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
245
威望
744 点
宅币
24265 个
贡献
46222 次
宅之契约
0 份
在线时间
2299 小时
注册时间
2014-1-26
发表于 2014-10-13 20:27:04 | 显示全部楼层
我注意到你的排版比起以前的帖子好多了
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-5-6 06:20 , Processed in 0.038258 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表