當你寫下new和delete的時候,到底發生了什麼事呢,讓我們來做個試驗看看。
寫一段小代碼:
- class a
- {
- public:
- a()
- {
- foo();
- }
- int foo()
- {
- return 0;
- }
- ~a()
- {
- bar();
- }
- int bar()
- {
- return 1;
- }
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- a* tmp = new a();
- delete tmp;
- return 0;
- }
在main函數的第一句下斷點,調試,然後開匯編窗口輸出結果:
- int _tmain(int argc, _TCHAR* argv[])
- {
- 004113F0 push ebp
- 004113F1 mov ebp,esp
- 004113F3 push 0FFFFFFFFh
- 004113F5 push offset __ehhandler$_wmain (41478Eh)
- 004113FA mov eax,dword ptr fs:[00000000h]
- 00411400 push eax
- 00411401 sub esp,100h
- 00411407 push ebx
- 00411408 push esi
- 00411409 push edi
- 0041140A lea edi,[ebp-10Ch]
- 00411410 mov ecx,40h
- 00411415 mov eax,0CCCCCCCCh
- 0041141A rep stos dword ptr es:[edi]
- 0041141C mov eax,dword ptr [___security_cookie (418000h)]
- 00411421 xor eax,ebp
- 00411423 push eax
- 00411424 lea eax,[ebp-0Ch]
- 00411427 mov dword ptr fs:[00000000h],eax
- /*a* tmp = new a();*/
- 0041142D push 1
- 0041142F call operator new (4111A4h)
- 00411434 add esp,4
- 00411437 mov dword ptr [ebp-0F8h],eax
- 0041143D mov dword ptr [ebp-4],0
- 00411444 cmp dword ptr [ebp-0F8h],0
- 0041144B je wmain+70h (411460h)
- 0041144D mov ecx,dword ptr [ebp-0F8h]
- 00411453 call a::a (41101Eh)
- 00411458 mov dword ptr [ebp-10Ch],eax
- 0041145E jmp wmain+7Ah (41146Ah)
- 00411460 mov dword ptr [ebp-10Ch],0
- 0041146A mov eax,dword ptr [ebp-10Ch]
- 00411470 mov dword ptr [ebp-104h],eax
- 00411476 mov dword ptr [ebp-4],0FFFFFFFFh
- 0041147D mov ecx,dword ptr [ebp-104h]
- 00411483 mov dword ptr [ebp-14h],ecx
- /*delete tmp;*/
- 00411486 mov eax,dword ptr [ebp-14h]
- 00411489 mov dword ptr [ebp-0E0h],eax
- 0041148F mov ecx,dword ptr [ebp-0E0h]
- 00411495 mov dword ptr [ebp-0ECh],ecx
- 0041149B cmp dword ptr [ebp-0ECh],0
- 004114A2 je wmain+0C9h (4114B9h)
- 004114A4 push 1
- 004114A6 mov ecx,dword ptr [ebp-0ECh]
- 004114AC call a::`scalar deleting destructor' (41117Ch)
- 004114B1 mov dword ptr [ebp-10Ch],eax
- 004114B7 jmp wmain+0D3h (4114C3h)
- 004114B9 mov dword ptr [ebp-10Ch],0
- /*return 0;*/
- 004114C3 xor eax,eax
- }
- 004114C5 mov ecx,dword ptr [ebp-0Ch]
- 004114C8 mov dword ptr fs:[0],ecx
- 004114CF pop ecx
- 004114D0 pop edi
- 004114D1 pop esi
- 004114D2 pop ebx
- 004114D3 add esp,10Ch
- 004114D9 cmp ebp,esp
- 004114DB call @ILT+345(__RTC_CheckEsp) (41115Eh)
- 004114E0 mov esp,ebp
- 004114E2 pop ebp
- 004114E3 ret
前面一片調整stack,插入安全代碼,設置異常處理等的操作不是今天我們要說的重點,直接跳到a* tmp = new a();這一句產生的反匯編:
- 0041142F call operator new (4111A4h)
我們很明確的看到調用了一個函數operator new。繼續跟進operator new看到底做了什麼事情:
- void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
- { // try to allocate size bytes
- void *p;
- while ((p = malloc(size)) == 0)
- if (_callnewh(size) == 0)
- { // report no memory
- static const std::bad_alloc nomem;
- _RAISE(nomem);
- }
- return (p);
- }
很意外吧,其實operator new函數就做了那麼一件事情:調用malloc函數分配內存。有沒有負責調用構造函數?這個真沒有。。。