c++ 内存管理

https://segmentfault.com/q/1010000000253786

内存管理有以下几个层次(从高到低):C程序 - C库(malloc)- 操作系统 - 物理内存

首先,操作系统保证每个进程都有独立的虚拟内存空间(32bit上应该是4G吧,一般进程也用不了这么多)。当然实际上物理内存是所有进程共享的,所以当你需要动态内存时,需要向操作系统申请,这时候虽然从你程序的角度,内存是连续的,其实是被操作系统映射到某一块物理内存而已。程序用完内存归还后,实际归还的部分可能被操作系统分配给其他进程。

要注意,上面说的“归还”是malloc库的行为。malloc库会使用一些策略来提高内存使用的效率,比如程序需要使用10K内存时,malloc实际可能上会申请1M,因为一次系统调用开销很大;再比如即使你调用了free“归还“了程序使用的内存,malloc库也可能并未真正把这些内存归还给操作系统,因为将来程序可能还会再申请动态内存。

malloc库有多种实现,我知道的一种是使用标记(tag)来存储内存的元信息。比如你申请了8个byte,得到的头指针地址是0x1001(实际内存为0x1001-0x1008),malloc会在0x1000(也就是头指针-1的位置)保存8,即这段内存的长度。等释放时,程序将头指针地址传给free,malloc库从头指针-1的位置发现需要释放的内存长度,释放内存(实际的操作可能只是将tag清空)。这就解释了:1. 为什么和malloc不同,free的参数只有一个头指针而不需要长度;2. free后内存实际上可能并未归还给操作系统。

所以,访问被(程序)释放的内存是一种undefined行为,就是说结果是不确定的。在malloc库未将此内存归还给操作系统也未进行下一次动态分配时,这块内存事实上仍属于程序。而当malloc库不清理归还的内存时(多数实现都是如此),你能访问到的值仍是原来的值。这和函数调用完毕而未清理栈帧、后续调用函数可以访问到之前已经设置的局部变量值是一个道理。

但是,当malloc库已经将内存归还给系统时,再去访问原来的地址(更别说写),由于这段地址已经不属于程序了,就会出现经典的segmentation fault。

说到底,这些现象还是C语言库为了更有效率的实现而妥协的结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值