c++ new[] delete[]底层分析

先写一个demo,里面有new[],delete[],使用C++11 MTd选项编译:


#include <string>
int main()
{
	auto pS = new std::string[10];
	
	delete[] pS;
	return 0;
}

new的大小为0x11c,十进制284,相当与10*28 + 4。4个额外申请的长度就是保存数组大小用的。

auto pS = new std::string[10];
009C970D  push        11Ch  
009C9712  call        operator new[] (09C376Ch)  
009C9717  add         esp,4  
009C971A  mov         dword ptr [ebp-0F8h],eax

在new返回的地址先写入的数组的长度10,注意返回给用户的地址是这个地址+4后的长度。

009C972E  je          main+9Ah (09C976Ah)  
009C9730  mov         eax,dword ptr [ebp-0F8h]  
009C9736  mov         dword ptr [eax],0Ah 

数组对象开始调用构造函数初始化:

009C973C  push        9C3FB9h  
009C9741  push        9C31DBh  
009C9746  push        0Ah  //对象的个数
009C9748  push        1Ch  //对象的大小
009C974A  mov         ecx,dword ptr [ebp-0F8h]  
009C9750  add         ecx,4  
009C9753  push        ecx  //将new返回的地址+4就是第一个对象的首地址
009C9754  call        `eh vector constructor iterator' (09C3EECh)  
009C9759  mov         edx,dword ptr [ebp-0F8h]  
009C975F  add         edx,4  
009C9762  mov         dword ptr [ebp-10Ch],edx
 //注意这里返回的地址是+4的,这是用户拿到的地址。复制流是这样的[ebp-10ch]->[ebp-104h]->ecx->pS
009C9768  jmp         main+0A4h (09C9774h)  
009C976A  mov         dword ptr [ebp-10Ch],0  
009C9774  mov         eax,dword ptr [ebp-10Ch]  
009C977A  mov         dword ptr [ebp-104h],eax  
009C9780  mov         dword ptr [ebp-4],0FFFFFFFFh  
009C9787  mov         ecx,dword ptr [ebp-104h]  
009C978D  mov         dword ptr [pS],ecx

所以我们调用new[]多个对象的时候,返回地址-4上保存着这个对象数组的大小。
接着我们看delete[]的时候是怎么用的:上来就是空指针检查,即使我们C++代码里面没有写。

delete[] pS;
009C9790  mov         eax,dword ptr [pS]  
009C9793  mov         dword ptr [ebp-0E0h],eax  
009C9799  mov         ecx,dword ptr [ebp-0E0h]  
009C979F  mov         dword ptr [ebp-0ECh],ecx  
009C97A5  cmp         dword ptr [ebp-0ECh],0  //检查pS是否为NULL
009C97AC  je          main+0F3h (09C97C3h)  
009C97AE  push        3  
delete[] pS;
009C97B0  mov         ecx,dword ptr [ebp-0ECh]  
009C97B6  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::`vector deleting destructor' (09C4216h)  

跟入vector deleting destructor函数看看:先[pS-4]取数组的的长度,调用析构函数,然后delete释放内存。

009C78DB  push        9C3FB9h  
009C78E0  mov         eax,dword ptr [this]  //取pS的值
009C78E3  mov         ecx,dword ptr [eax-4]  //取对象数组的长度
009C78E6  push        ecx  //string对象的个数10
009C78E7  push        1Ch  //strig对象的大小
009C78E9  mov         edx,dword ptr [this]  
009C78EC  push        edx  
009C78ED  call        `eh vector destructor iterator//调用string析构函数
009C78F2  mov         eax,dword ptr [ebp+8]  
009C78F5  and         eax,1  
009C78F8  je          std::basic_string<char,std::char_traits<char>,std::allocator<char> >::`vector deleting destructor'+59h (09C7909h)  
009C78FA  mov         eax,dword ptr [this]  
009C78FD  sub         eax,4  //pS-4才是申请堆block的首地址,然后delete释放。
009C7900  push        eax  
009C7901  call        operator delete[] (09C3136h)  
009C7906  add         esp,4 

总结:delete[]参数不用输入数组的长度,是CRT实现new的时候在堆userdata首地址放上了数组长度,new返回的地址是申请到地址+4的值。然后delete[]释放的时候,用传入地址-4拿数组长度,实现数组释放。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值