动态内存分配是在堆上分配的,且自己分配的,必须要自己释放,否则就会内存泄漏,具体C++怎么实现的呢?
老规矩,先上C++验证代码:
#include
// #include
/**
* 内存管理:堆区内存分配
*/
int main(){
int *arr = new int[11];
arr[0] = 0;
arr[9] = 9;
arr[88] = 88;// 越界
// std::cout
上面C++代码,分别用new/delete分配释放堆内存,又用malloc/free分配释放内存,且还进行了越界赋值,看看什么效果。,下面是对应的汇编:
main:
.LFB1522:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
# new/delete
movl $44, %edi # 申请分配44个字节
call _Znam@PLT
movq %rax, -16(%rbp) # rax里是函数返回值,rbp-8存储这块堆内存的地址
movq -16(%rbp), %rax
movl $0, (%rax) # 堆内存+0的地址赋值为0,即第0个元素
movq -16(%rbp), %rax
addq $36, %rax
movl $9, (%rax) # # 9 * 4 == 36,即第9个元素
movq -16(%rbp), %rax
addq $352, %rax # 88 * 4 = 352
movl $88, (%rax) # 越界赋值88
cmpq $0, -16(%rbp) # 空指针检查, 如果相等,那么零标志(ZF)将被设置为1,否则将被设置为0。
je .L2 # je .L2指令检查零标志,如果它为1,则跳转到.L2标签处
movq -16(%rbp), %rax
movq %rax, %rdi
call _ZdaPv@PLT
# malloc/free
.L2:
movl $44, %edi
call malloc@PLT # malloc分配44字节
movq %rax, -8(%rbp)
movq -8(%rbp), %rax
movl $0, (%rax)
movq -8(%rbp), %rax
addq $36, %rax
movl $9, (%rax)
movq -8(%rbp), %rax
addq $352, %rax # 越界赋值
movl $88, (%rax)
movq -8(%rbp), %rax
movq %rax, %rdi
call free@PLT # 不做空指针检查,直接调用free去释放
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
根据上述汇编可知,汇编上直接调用的是系统调用的动态链接库,具体new/delete、malloc/free的实现代码,需要自己看内核源码,回头研究研究。但是基本上我们可以宏观知道,C++编译器只管调用系统调用,去给你分配释放内存,而且必须是你自己执行delete/free了之后,它才会取调用对应的系统调用去释放对应的堆内存,如果你C++代码里不执行delete/free,那么C++编译器也不会帮你检查。
所以,应用堆内存,一定要小心,注意释放,否则就会出现内存泄漏问题。
另外,越界问题C++也不会帮你检查,直接就从数组的起始位置计算第88个元素的地址,然后直接帮你越界赋值了,其实这是错的,如果真实的程序中,可能会破坏有效数据。所以要注意数组下标的控制。
现在明白了,堆内存的分配与释放也是比较简单的。
总结
这几篇文章,分别探索了栈内存、数据段、只读数据段、代码段、堆内存的分配问题,我现在是比较直观的理解了这些内存的分配情况是怎么回事。
简而言之,栈内存、数据段、代码段的内存分配、内存的相对地址,都是编译器提前计算好的,即都是在编译期确定好的。从汇编程序里也可以看出,所以的标号的寻址用的都是相对地址,相对于rbp寄存器或者rip的地址。
而堆内存的分配,是动态的,当调用系统调用进行分配的时候,系统调用里的代码会自动寻找一块区域分配给用户程序,每一次分配都是不确定的,所以它无法在编译期进行确定!
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
相关推荐: 华为手机自带浏览器在web网页中对长按保存无法禁止?
在最近的开发过程中,遇到一个问题,在实现拖动图片(img标签)时,如果未拖动而长按图片,会触发保存功能。在对标签进行CSS设置以后,其他的浏览器都已禁止了长按保存功能,现在只留下华为自带的浏览器还存在长按保存的功能。 -webkit-touch-callout…