小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

關于new和delete 一些不得不說的事

 9loong 2009-11-25
http://developer.51cto.com/art/200906/131853.htm
 
2009-06-26 11:01  gussing  
    new和delete在C++中作用很大,但是當你寫下new和delete的時候,到底發(fā)生了什么事,你了解過嗎?本文為你講述當你寫下new和delete的時候,到底發(fā)生了什么事。

    當你寫下new和delete的時候,到底發(fā)生了什么事呢,讓我們來做個試驗看看。

    寫一段小代碼:

            
    1. class a  
    2. {  
    3. public:  
    4.  a()  
    5.  {  
    6.   foo();  
    7.  }  
    8.  int foo()  
    9.  {  
    10.   return 0;  
    11.  }  
    12.  
    13.  ~a()  
    14.  {  
    15.   bar();  
    16.  }  
    17.  
    18.  int bar()  
    19.  {  
    20.   return 1;  
    21.  }  
    22. };  
    23.  
    24. int _tmain(int argc, _TCHAR* argv[])  
    25. {  
    26.  a* tmp = new a();  
    27.  delete tmp;  
    28.  return 0;  
    29. }  

    在main函數(shù)的第一句下斷點,調試,然后開匯編窗口輸出結果:

            
    1. int _tmain(int argc, _TCHAR* argv[])  
    2. {  
    3. 004113F0  push        ebp    
    4. 004113F1  mov         ebp,esp   
    5. 004113F3  push        0FFFFFFFFh   
    6. 004113F5  push        offset __ehhandler$_wmain (41478Eh)   
    7. 004113FA  mov         eax,dword ptr fs:[00000000h]   
    8. 00411400  push        eax    
    9. 00411401  sub         esp,100h   
    10. 00411407  push        ebx    
    11. 00411408  push        esi    
    12. 00411409  push        edi    
    13. 0041140A  lea         edi,[ebp-10Ch]   
    14. 00411410  mov         ecx,40h   
    15. 00411415  mov         eax,0CCCCCCCCh   
    16. 0041141A  rep stos    dword ptr es:[edi]   
    17. 0041141C  mov         eax,dword ptr [___security_cookie (418000h)]   
    18. 00411421  xor         eax,ebp   
    19. 00411423  push        eax    
    20. 00411424  lea         eax,[ebp-0Ch]   
    21. 00411427  mov         dword ptr fs:[00000000h],eax   
    22.  /*a* tmp = new a();*/ 
    23. 0041142D  push        1      
    24. 0041142F  call        operator new (4111A4h)   
    25. 00411434  add         esp,4   
    26. 00411437  mov         dword ptr [ebp-0F8h],eax   
    27. 0041143D  mov         dword ptr [ebp-4],0   
    28. 00411444  cmp         dword ptr [ebp-0F8h],0   
    29. 0041144B  je          wmain+70h (411460h)   
    30. 0041144D  mov         ecx,dword ptr [ebp-0F8h]   
    31. 00411453  call        a::a (41101Eh)   
    32. 00411458  mov         dword ptr [ebp-10Ch],eax   
    33. 0041145E  jmp         wmain+7Ah (41146Ah)   
    34. 00411460  mov         dword ptr [ebp-10Ch],0   
    35. 0041146A  mov         eax,dword ptr [ebp-10Ch]   
    36. 00411470  mov         dword ptr [ebp-104h],eax   
    37. 00411476  mov         dword ptr [ebp-4],0FFFFFFFFh   
    38. 0041147D  mov         ecx,dword ptr [ebp-104h]   
    39. 00411483  mov         dword ptr [ebp-14h],ecx   
    40.  /*delete tmp;*/ 
    41. 00411486  mov         eax,dword ptr [ebp-14h]   
    42. 00411489  mov         dword ptr [ebp-0E0h],eax   
    43. 0041148F  mov         ecx,dword ptr [ebp-0E0h]   
    44. 00411495  mov         dword ptr [ebp-0ECh],ecx   
    45. 0041149B  cmp         dword ptr [ebp-0ECh],0   
    46. 004114A2  je          wmain+0C9h (4114B9h)   
    47. 004114A4  push        1      
    48. 004114A6  mov         ecx,dword ptr [ebp-0ECh]   
    49. 004114AC  call        a::`scalar deleting destructor' (41117Ch)   
    50. 004114B1  mov         dword ptr [ebp-10Ch],eax   
    51. 004114B7  jmp         wmain+0D3h (4114C3h)   
    52. 004114B9  mov         dword ptr [ebp-10Ch],0   
    53.  /*return 0;*/ 
    54. 004114C3  xor         eax,eax   
    55. }  
    56. 004114C5  mov         ecx,dword ptr [ebp-0Ch]   
    57. 004114C8  mov         dword ptr fs:[0],ecx   
    58. 004114CF  pop         ecx    
    59. 004114D0  pop         edi    
    60. 004114D1  pop         esi    
    61. 004114D2  pop         ebx    
    62. 004114D3  add         esp,10Ch   
    63. 004114D9  cmp         ebp,esp   
    64. 004114DB  call        @ILT+345(__RTC_CheckEsp) (41115Eh)   
    65. 004114E0  mov         esp,ebp   
    66. 004114E2  pop         ebp    
    67. 004114E3  ret     

    前面一片調整stack,插入安全代碼,設置異常處理等的操作不是今天我們要說的重點,直接跳到a* tmp = new a();這一句產生的反匯編:

            
    1. 0041142F call operator new (4111A4h) 

    我們很明確的看到調用了一個函數(shù)operator new。繼續(xù)跟進operator new看到底做了什么事情:

            
    1. void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)  
    2.         {       // try to allocate size bytes  
    3.         void *p;  
    4.         while ((p = malloc(size)) == 0)  
    5.                 if (_callnewh(size) == 0)  
    6.                 {       // report no memory  
    7.                 static const std::bad_alloc nomem;  
    8.                 _RAISE(nomem);  
    9.                 }  
    10.  
    11.         return (p);  
    12.         }  

    很意外吧,其實operator new函數(shù)就做了那么一件事情:調用malloc函數(shù)分配內存。有沒有負責調用構造函數(shù)?這個真沒有。。。

    那構造函數(shù)到底是誰調用的?看operator new下面的那片匯編代碼:

            
    1. 00411434  add         esp,4   
    2. 00411437  mov         dword ptr [ebp-0F8h],eax   
    3. 0041143D  mov         dword ptr [ebp-4],0   
    4. 00411444  cmp         dword ptr [ebp-0F8h],0   
    5. 0041144B  je          wmain+70h (411460h)   
    6. 0041144D  mov         ecx,dword ptr [ebp-0F8h]   
    7. 00411453  call        a::a (41101Eh)  

    出去將返回值賦給tmp的操作,我們看到了一處函數(shù)調用:

            
    1. 00411453 call a::a (41101Eh)  

    沒錯,對類a的構造函數(shù)的調用,是編譯器偷偷在你的函數(shù)里插入的,當時的情況就是如此。delete的情況也是一摸一樣。
    再來看針對對象數(shù)組的new和delete:

            
    1. class a  
    2. {  
    3. public:  
    4.  a()  
    5.  {  
    6.   int i1;  
    7.   int j1 = 0;  
    8.   static int k1;  
    9.   static int l1 = 0;  
    10.   foo();  
    11.  }  
    12.  int foo()  
    13.  {  
    14.   return 0;  
    15.  }  
    16.  
    17.  ~a()  
    18.  {  
    19.   int i2;  
    20.   int j2 = 0;  
    21.   static int k2;  
    22.   static int l2 = 0;  
    23.   bar();  
    24.  }  
    25.  
    26.  int bar()  
    27.  {  
    28.   return 1;  
    29.  }  
    30. };  
    31.  
    32. int _tmain(int argc, _TCHAR* argv[])  
    33. {  
    34.  a* tmp = new a[10];  
    35.  delete[] tmp;  
    36.  return 0;  
    37. }  

    反匯編之后的結果如下:

            
    1. int _tmain(int argc, _TCHAR* argv[])  
    2. {  
    3. 004113F0  push        ebp    
    4. 004113F1  mov         ebp,esp   
    5. 004113F3  push        0FFFFFFFFh   
    6. 004113F5  push        offset __ehhandler$_wmain (41478Eh)   
    7. 004113FA  mov         eax,dword ptr fs:[00000000h]   
    8. 00411400  push        eax    
    9. 00411401  sub         esp,100h   
    10. 00411407  push        ebx    
    11. 00411408  push        esi    
    12. 00411409  push        edi    
    13. 0041140A  lea         edi,[ebp-10Ch]   
    14. 00411410  mov         ecx,40h   
    15. 00411415  mov         eax,0CCCCCCCCh   
    16. 0041141A  rep stos    dword ptr es:[edi]   
    17. 0041141C  mov         eax,dword ptr [___security_cookie (418000h)]   
    18. 00411421  xor         eax,ebp   
    19. 00411423  push        eax    
    20. 00411424  lea         eax,[ebp-0Ch]   
    21. 00411427  mov         dword ptr fs:[00000000h],eax   
    22.  a* tmp = new a[10];  
    23. 0041142D  push        0Eh    
    24. 0041142F  call        operator new (4111A4h)   
    25. 00411434  add         esp,4   
    26. 00411437  mov         dword ptr [ebp-0F8h],eax   
    27. 0041143D  mov         dword ptr [ebp-4],0   
    28. 00411444  cmp         dword ptr [ebp-0F8h],0   
    29. 0041144B  je          wmain+97h (411487h)   
    30. 0041144D  mov         eax,dword ptr [ebp-0F8h]   
    31. 00411453  mov         dword ptr [eax],0Ah   
    32. 00411459  push        offset a::`scalar deleting destructor' (41100Ah)   
    33. 0041145E  push        offset a::a (41101Eh)   
    34. 00411463  push        0Ah    
    35. 00411465  push        1      
    36. 00411467  mov         ecx,dword ptr [ebp-0F8h]   
    37. 0041146D  add         ecx,4   
    38. 00411470  push        ecx    
    39. 00411471  call        `eh vector constructor iterator' (4111F9h)   
    40. 00411476  mov         edx,dword ptr [ebp-0F8h]   
    41. 0041147C  add         edx,4   
    42. 0041147F  mov         dword ptr [ebp-10Ch],edx   
    43. 00411485  jmp         wmain+0A1h (411491h)   
    44. 00411487  mov         dword ptr [ebp-10Ch],0   
    45. 00411491  mov         eax,dword ptr [ebp-10Ch]   
    46. 00411497  mov         dword ptr [ebp-104h],eax   
    47. 0041149D  mov         dword ptr [ebp-4],0FFFFFFFFh   
    48. 004114A4  mov         ecx,dword ptr [ebp-104h]   
    49. 004114AA  mov         dword ptr [ebp-14h],ecx   
    50.  delete[] tmp;  
    51. 004114AD  mov         eax,dword ptr [ebp-14h]   
    52. 004114B0  mov         dword ptr [ebp-0E0h],eax   
    53. 004114B6  mov         ecx,dword ptr [ebp-0E0h]   
    54. 004114BC  mov         dword ptr [ebp-0ECh],ecx   
    55. 004114C2  cmp         dword ptr [ebp-0ECh],0   
    56. 004114C9  je          wmain+0F0h (4114E0h)   
    57. 004114CB  push        3      
    58. 004114CD  mov         ecx,dword ptr [ebp-0ECh]   
    59. 004114D3  call        a::`vector deleting destructor' (4111F4h)   
    60. 004114D8  mov         dword ptr [ebp-10Ch],eax   
    61. 004114DE  jmp         wmain+0FAh (4114EAh)   
    62. 004114E0  mov         dword ptr [ebp-10Ch],0   
    63.  return 0;  
    64. 004114EA  xor         eax,eax   
    65. }  
    66. 004114EC  mov         ecx,dword ptr [ebp-0Ch]   
    67. 004114EF  mov         dword ptr fs:[0],ecx   
    68. 004114F6  pop         ecx    
    69. 004114F7  pop         edi    
    70. 004114F8  pop         esi    
    71. 004114F9  pop         ebx    
    72. 004114FA  add         esp,10Ch   
    73. 00411500  cmp         ebp,esp   
    74. 00411502  call        @ILT+345(__RTC_CheckEsp) (41115Eh)   
    75. 00411507  mov         esp,ebp   
    76. 00411509  pop         ebp    
    77. 0041150A  ret           
    78.   

    其他部分都大同小異,關鍵的不同在編譯器插入的,用于初始化的代碼:

            
    1. 00411459  push        offset a::`scalar deleting destructor' (41100Ah)   
    2. 0041145E  push        offset a::a (41101Eh)   
    3. 00411463  push        0Ah    
    4. 00411465  push        1      
    5. 00411467  mov         ecx,dword ptr [ebp-0F8h]   
    6. 0041146D  add         ecx,4   
    7. 00411470  push        ecx    
    8. 00411471  call        `eh vector constructor iterator' (4111F9h) 

    我們看到數(shù)組大小0Ah,構造函數(shù)的地址41101Eh都被壓入棧中,作為某函數(shù)的參數(shù)。到底是什么函數(shù)呢?就是:

            
    1. 00411471  call        `eh vector constructor iterator' (4111F9h) 

    一個名為`eh vector constructor iterator' 的函數(shù)。我們還注意到a類的析構函數(shù)的地址也被當成參數(shù)傳入,這是干什么用的呢?構造函數(shù)里為什么要析構函數(shù)的地址?比如在遍歷調用構造函數(shù)的過程中,前8個都是沒問題的,到第9個突然資源不足調用失敗了,那么在返回前無論如何也要先把前8個的析構函數(shù)調用一遍,防止資源泄露。

    delete[]的過程也大同小異,不過一個很有趣的地方是,“vector deleting destructor'”是a類的成員函數(shù),而與‘eh vector constructor iterator’對應的`eh vector destructor iterator'函數(shù)在“vector deleting destructor'”函數(shù)內部:

            
    1. 004134AD  call        `eh vector destructor iterator' (411203h)  

    。。。

            
    1. 004134C1  call        operator delete (4110A0h) 

    回收內存的操作,也在a::`vector deleting destructor'里。

     

    (#)

 

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多