一个运行程序是一定有四个区域,分别是:代码区,数据区,栈区,堆区。
栈区我们知道,是函数传参保存临时变量的一段内存空间。那么堆区是干嘛的呢?
堆区就是动态开辟的一块内存空间,用于存放数据。在C语言中,我们是用malloc函数去开辟空间的,释放空间是free函数。而在C++中用的是New关键字,释放空间用的是Delete关键字。
C语言的malloc和C++中的New有啥区别?
其实本质上他们没有什么区别。New相当于对malloc又做了一层封装,调用new会自动调用构造函数,而malloc不会。
我们写一个小的demo从汇编的角度看待问题,代码如下:
#include<iostream>
using namespace std;
int *func1(){
int *p=new int(10);
return p;
}
int main(){
int *ret=func1();
cout<<"number= "<<*ret<<endl;
return 0;
}
代码非常简单。就是在堆区创建一个int大小的空间并赋值为10。
下面我们观察下过程:
一进来就是调用我们的fun1函数。s跟进看看:
一开始我们看到传参4字节大小。因为我们创建的Int类型就是四字节。紧接着就去调用一个目前未知的函数,跟进去看看:
反汇编跟进这个地址我们看到是会调用一个函数。这个函数应该就是New的构造函数。紧接着s跟进,就会来到这里:
我们观察到,做了一些初始化后,最后还是调用C语言的malloc函数。因此验证了我们上述的New其实就是对malloc做的再一次封装。供C++调用。更加符合C++的语法规范。
单步到这,我们发现edi就是我们的malloc函数的参数。相当于调用malloc(0x4)。执行完malloc返回值将会放到rax中:
我们看到堆的返回地址已经在RAX寄存器中了。现在我们看这片空间是没有东西的,只是初始化了这么一块空间给用户:
因为在C语言的malloc管理中,64位下的堆其实是有0x10大小的堆头的也就是16字节。0x555555767e70的位置才是用户可操作的空间。
接下来如果我们执行,堆上将会写入一个0xa我们观察下效果:
结果是符合预期的。那么相同道理,Delete的操作应该类似。将free函数进行一层封装,底层依然是调用的free函数: