内存泄漏以及常见的解决方法

最近一直在忙项目,有点耽搁了吐舌头  

前段时间花费了很大的精力在已经成熟的代码上再去处理memory leak问题。今天就来详细说一下,看看它是什么和常见的几种解决办法有哪些。

写此的目的是希望我们应该养成良好的编码习惯,尽可能的避免这样的问题,因为当你对着一大片的代码再去处理此类的问题,此时无疑增加了解决的成本和难度。准确的说属于补救措施了。


1. 什么是内存泄漏(memory leak)?

指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。 

A memory leak is a particular type of unintentional memory consumption by a computer program where the program fails to release memory when no longer needed. This condition is normally the result of a bug in a program that prevents it from freeing up memory that it no longer needs.This term has the potential to be confusing, since memory is not physically lost from the computer. Rather, memory is allocated to a program, and that program subsequently loses the ability to access it due to program logic flaws. 


2. 如何解决内存泄露?


内存泄露的问题其困难在于:

1.编译器不能发现这些问题。

2.运行时才能捕获到这些错误,这些错误没有明显的症状,时隐时现。

3.对于手机等终端开发用户来说,尤为困难。下面从三个方面来解决内存泄露:



①,良好的编码习惯,尽量在涉及内存的程序段,检测出内存泄露。当程式稳定之后,在来检测内存泄露时,无疑增加了排除的困难和复杂度。

使用了内存分配的函数,一旦使用完毕,要记得要使用其想用的函数释放掉。



Heap memory:

malloc\realloc ------  free

new \new[] ----------  delete \delete[]

GlobalAlloc------------GlobalFree 



②要特别注意数组对象的内存泄漏

     MyPointEX *pointArray =new MyPointEX [100];

      其删除形式为:
     delete []pointArray 

③Resource Leak :对于系统资源使用之前要仔细看起使用方法,防止错误使用或者忘记释放掉系统资源。

如果使用完成时候忘记释放字体,就造成了资源泄漏。 


④对于基于引用计数的系统对象尤其要注意,因为只有其引用计数为0时,该对象才能正确被删除。而其使用过程中有其生成的新的系统资源,使用完毕后,如果没有及时删除,都会影响其引用计数。


对于资源,也可使用RAII,RAII(Resource acquisition is initialization)资源获取即初始化,它是一项很简单的技术,利用C++对象生命周期的概念来控制程序的资源,例如内存,文件句柄,网络连接以及审计追踪(audit trail)等.RAII的基本技术原理很简单.若希望保持对某个重要资源的跟踪,那么创建一个对象,并将资源的生命周期和对象的生命周期相关联.如此一来,就可以利用C++复杂老练的对象管理设施来管理资源.(有待完善) 



⑤重载  new 和 delete。这也是大家编码过程中常常使用的方法。


其主要思路是将分配的内存以链表的形式自行管理,使用完毕之后从链表中删除,程序结束时可检查改链表,其中记录了内存泄露的文件,所在文件的行数以及泄露的大小哦。


⑥ Boost 中的smart pointer(待完善,结合大家的建议)


⑦ 一些常见的工具插件




3. 由内存泄露引出内存溢出话题:


所谓内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是会产生内存溢出的问题。


常见的溢出主要有:



内存分配未成功,却使用了它。
常用解决办法是,在使用内存之前检查指针是否为NULL。如果指针p 是函数的参数,那么在函数的入口处用assert(p!=NULL)进行检查。如果是用malloc 或new 来申请内存,应该用if(p==NULL)或if(p!=NULL)进行防错处理。



内存分配虽然成功,但是尚未初始化就引用它。
内存分配成功并且已经初始化,但操作越过了内存的边界。
例如在使用数组时经常发生下标“多1”或者“少1”的操作。特别是在for 循环语句中,循环次数很容易搞错,导致数组操作越界。



使用free 或delete 释放了内存后,没有将指针设置为NULL。导致产生“野指针”。



程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。(这点可是深有感受,呵呵)


不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值