细数两种内存泄露方式

常见的两类内存泄露:

  1. 在程序中不停的new 内存,但是没有释放,这种情况很可能会触发std::bad_alloc异常,.dmp文件中,!address -summary的最后一栏是Largest Free Region,这里最大的值一般都小于要分配的大小,也就是虚拟内存不足以提供足够大的连续空间,所以报异常,报异常的时候,查看当前的物理内存和虚拟内存的剩余空间,一般都是还有空间的。所以,这里的“连续空间”指的只是虚拟内存的空间,并非是连续的物理内存空间,因为虚拟映射到物理是可以乱序映射的。

  2. 另一种是不停的创建handle但是不close,这种情况下触发的是handle泄露,但其实handle也会占用一些内存,这部分内存如果在任务管理中查看内存占用,是不会逐渐增加的,但是系统的内存确实在逐步的耗尽,并且如果关闭进程,这部分内存也随之被释放,所以现在的操作系统对内存的管理已经相当复杂,不太好用一句话定义进程占用了多少内存。就像这个handle占用的内存(100~200KB左右),到底算是进程占用的,还是不算呢?若说算,在资源管理器中看到的就不增加,若说不算,杀掉该进程后,就随即回收了。那这一部分内存在哪里可以直观的看到呢?

在资源管理器有个已提交,/前面就是提交的内存数量,后面是当前总的虚拟内存的空间,每次申请handle,则已提交就会增加100~200KB,若系统的虚拟内存空间还可以增长,则如果提交到一定的数量后,/后面的总的虚拟内存也会增加,系统会自动的增长虚拟内存的数值来满足需求。

问题来了,虚拟内存的大小最大能增长到多少?答:物理内存的值+设置的虚拟内存大小,也就是可以用磁盘保存的内存大小,具体的磁盘文件是pagefile.sys,物理内存就交换到这个文件中。

第一栏是使用中,这个其实就是已经使用的物理内存和总的物理内存,可以看到,虽然有虚拟内存的存在,但是系统总是把可用的物理内存和可用的虚拟内存的大小保持差不多大。

如果commit虚拟内存达到的限制,会报这个错误:1455(ERROR_COMMITMENT_LIMIT), 如果刚才的bad_alloc,会报 错误码8(ERROR_NOT_ENOUGH_MEMORY),可以用GetLastError获取。

这里说一下内存的申请步骤:当像操作系统申请大小为N内存时,系统会在虚拟内存中找这么大的连续空间,如果没有这么大的,则直接报错bad_alloc并返回,如果有,则已提交的内存会增加N,注意这里只是commit,还没有和真正的物理内存挂钩,直到该内存真正的被使用时,比如new char[N](); 这个括号就是真正的使用,相当于memset,或者直接用memset都探一遍时,虚拟内存才会和物理内存挂钩,此时引发一个缺页中断,虚拟内存和物理内存建立联系,此时可用的物理内存才会减少N,可见,内存分配也采用了类型的“懒加载"的策略。

还有没有地方可以查看像刚才的handle占用的内存的工具呢?还是祭出process explorer,share commit一栏就代表刚才说的这种内存。

linux内存分配理解:内存大小的基本单位是页,默认页大小是4KB,虽然虚拟内存和物理内存的映射是乱序的,但是一个页内部应该是顺序相同的,物理内存的一个页也是4K,并且映射也是以页为基本单位的。

用户态的函数mallock和free分配,底层会调用brk和mmap和unmap, brk是分配小于128KB的大小时,并不从MMU中去找空闲内存,而是移动edata指针,这个是数据段的最高位,也就在数据段和heap之间,预留了这一小段空间用于小内存分配,用于提高效率,比如我连续分配了A(10K), B(20K), C(30K)3个内存,那么edata指针会移动60K,然后我接着去释放A,由于edata指针不能移动(否则B,C就被销毁了),所以只能把A的内存标记为释放,A映射的物理内存和虚拟地址都没有释放,这也就是内存碎片的由来,当free(C)时,必须A和B都已经被释放了,则edata指针才会往回移动。

mmap用于分配大于128KB的内存,过程和刚才window上分配就很类似了,也是同样的懒加载”用到的时候,才真正的挂物理内存。注意:和windows一样,这里挂物理内存,实际上可能是磁盘,也可能是内存!!如果挂的是硬盘,则速度会非常慢!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值