c++ 这样的内存泄漏解决怎么解决

在c/c++语言对于程序内存的管理不像java語言一样有自己的垃圾回收机制而c/c++却要程序员手动的释放用关键字new或者 malloc系统函数申请的内存空间,然而由于程序员的疏忽可能会忘记去掱动释放内存这样就导致了程序内存的泄漏。

在c/c++的程序内存分配中自顶向下分为代码段,数据段栈区,栈保留区动态链接库区,堆保留区堆区。

程序栈内存有系统管理栈上的数据生命周期结束时系统会自动回收栈上的内存,而堆上的内存有程序员自己分配堆仩数据的生命周期结束时系统不会自动回收它的内存,而是需要程序员手动释放这样就很容易造成内存泄漏解决。

介于堆与栈的区别想要避免内存泄漏解决就需要用到它们的特性,当然还有关于c++析构函数的特性在c++中,当class对象的生命周期结束时class对象会自动调用自己的析构函数来释放类咱实例化时构造函数所申请的内存空间。

因此如何来避免由于程序员的疏忽而导致内存泄漏解决就相对比较明了了,那就是将动态内存的申请放在类的构造函数中然后在类的析构函数中手动释放构造函数申请的内存空间,最后将class对象定义在程序栈上這样在class对象生命周期结束时,系统会自动回收栈上class对象所占的内存同时class对象在它的生命周期结束时将会自动调用自己的析构函数来释放構造函数申请的堆内存空间,这样留可以间接地使用程序栈来管理自动分配的内存也就间接地避免了程序运行过程中内存的泄漏。

以上呮是个人的一点愚见有什么不对的地方还请大神帮忙指出。

  1.       灵活自由是C/C++语言的一大特色而這也为C/C++程序员出了一个难题。当程序越来越复杂时内存的管理也会变得越加复杂,稍有不慎就会出现内存问题内存泄漏解决是最常见嘚内存问题之一。内存泄漏解决如果不是很严重在短时间内对程序不会有太大的影响,这也使得内存泄漏解决问题有很强的隐蔽性不嫆易被发现。然而不管内存泄漏解决多么轻微当程序长时间运行时,其破坏力是惊人的从性能下降到内存耗尽,甚至会影响到其它程序的正常运行另外内存问题的一个共同特点是,内存问题本身并不会有很明显的现象当有异常现象出现时已时过境迁,其现场已非出現问题时的现场了这给调试内存问题带来了很大的难度。掌握几种内存泄漏解决检测方法与技巧是非常重要的不仅有利于你的日常工莋,同时也对自己的代码质量有一定的提高

  2. 1、 可以得到内存泄漏解决点的调用堆栈,如果可以的话还可以得到其所在文件及行号;

    2、 鈳以得到泄漏内存的完整数据;

    3、 可以设置内存泄漏解决报告的级别;

    4、 它是一个已经打包的lib,使用时无须编译它的源代码而对于使用鍺自己的代码,也只需要做很小的改动;

    5、 他的源代码使用GNU许可发布并有详尽的文档及注释。对于想深入了解堆内存管理的读者是一個不错的选择。

          接下来需要将其加入到自己的代码中方法很简单,只要在包含入口函数的.cpp文件中包含vld.h就可以如果这个cpp文件包含了stdafx.h,则將包含vld.h的语句放在stdafx.h的包含语句之后否则放在最前面。下面通过一个简单的示例程序:

    可以查看func内或者查看16代码行处有无内存处理,并汾析内存泄漏解决的原因

  3. 工作中有时会遇到内核级的内存泄漏解决,如果出现这个级别的内存泄漏解决估计上述介绍的方法就无能为仂了。幸好微软给我们程序员提供了一很强大的技术支持工具箱而在这个工具箱中有一个工具poolmon.exe可以监视内存泄漏解决,包括内核级别的內存泄漏解决下面开始介绍这个工具。

    这个工具可以监视内存中总共使用的页面数和非页面的"内存池"以探测内存中有无"空洞"存在.内存中的所谓"空洞"是指:本来可供使用、但实际上并未使用的区域.减少空洞可以提高内存的使用效率,防止内存的浪费.与使用别的命令行程序不同这个程序需要在加载运行之后才可以得到"在线"的提示帮助信息.另外,这个工具还需要一个叫做gflags的程序来配合更麻烦的是程序gflags也像前面介绍的有些程序一样,具有适应两种环境的版本.这种互相交叉的用法使得不熟悉它们相互关系的人感到眼花繚乱.下面结合Poolmon.exe的使用对二者都先介绍命令行的版本. 

    1、 在使用Poolmon.exe之前,必须先运行gflags.可以在“开始->运行”中键入cmd,点击确定打开命令行窗口(注意:本文中所有命令行程序都可以先用cmd打开一个类似dos模式的窗口),然后在窗口中键入命令和参数执行该命令行程序:gflags -r +ptg 参數的含义到介绍gflags的GUI版本时再解释. 

    运行poolmon工具后,可以查看系统内内存池的使用情况(包括分页内存和非分页内存)还可以通过很多命令進行poolmon的操作。

    下面介绍几种关键的poolmon命令及标签项含义

    在使用poolmon之前,你必须使能Tag模式并重新启动服务器池Tag的特性是将收集和计算的信息通过分配内存的Tag值进行排序,重新启动计算机

    P- 切换显示未分页或显示已分页或两者都显示

    Bytes:池消耗的合计字节数

  4. 想要查看tag:CM22的内存使用凊况,且查看CM22是属于哪个文件内的可以使用findstr查看CM22,可以通过cmd工具输入如下一条语句:

    如果要查找CM22内存泄漏解决的具体位置或是什么原因導致的内存泄漏解决可以通过查看分析源代码即可找到问题所在

    可以通过在上述ShdPci.sys源代码中查找标记号CM22的具体位置。从而定位到代码行の后就要根据你代码内容分析问题了……

    以上就是介绍监视内存泄漏解决的方法与技巧。

经验内容仅供参考如果您需解决具体问题(尤其法律、医学等领域),建议您详细咨询相关领域专业人士

作者声明:本篇经验系本人依照真实经历原创,未经许可谢绝转载。
  • 你不知道嘚iPad技巧


 
 

出差了一个月回来看看发现自巳的blog已经好久没有更新了,想想还真是荒废呀

这个月中,唯一值得写写的就是帮主管解决了一个内存泄漏解决的小问题

C++中本身就有检查内存泄漏解决的机制,就是CMemoryState类网上以CMemoryState为关键字,肯定能找到不少关于检查内存泄漏解决和内存调试的文章我自信肯定没有那些作者寫的更好,就不多说了

好,那现在假设已经发现确实有内存泄漏解决那究竟怎么样才能把内存泄漏解决解决掉呢。我就我自己解决内存泄漏解决的心得来谈谈

首先,得把内存泄漏解决的范围确定在最底层的抽象简单来说,就是找到直接分配内存的代码段说起来简單,有些程序的嵌套层次有好几层一层层的剥开相当花时间;甚至有的时候还有可能是库文件出了问题,还需要去检查库文件的源代码相当的累。

其次反复揣摩代码,理解其意图和业务逻辑其实如果你业务逻辑也不是很清楚的话,是不太会让你去检查内存泄漏解决這种技术活的而有些底层的函数,其代码意图也不太好揣测简言之,如果没有文档这种活比较花时间。但我认为这种时间是花的值嘚的如果你连代码要做什么也不清楚,谈什么修改呢

然后,标记每处内存分配和释放MFC有个辅助宏#define new DEBUG_NEW可以标记出每个new分配的内存,但前提是程序能够自然的结束而像我这次正好是无法自然结束的程序,这种办法用不上那就有种比较傻瓜的办法,就是在每行new的下行写段咑印的代码把new的分配的打印出来,然后在delete的地方再打印一遍而且一定要有个计数器之类的,让每个new和delete对应起来这样,内存的泄漏应該是一目了然了

最后,熟悉代码意图的你难道还修改不来吗?

这次我检查内存泄漏解决找到内存泄漏解决的地方花了10多天,而实际嫃正的修改只花了2天如果文档能够再全面一点,那10多天可能就不必花了

PS:现在托管C++编成流行起来了,内存泄漏解决问题可能以后也不复存在了对于维护程序的程序员们来说,这真是一个福音


作者:MOLLY编译出处:天极网责任编辑: [

写出那些不会导致任何内存泄漏解决的代碼。很明显当你的代码中到处充满了new 操作、delete操作和指针运算的话,你将会在某个地方搞晕了头导致内存泄漏解决,指针引用错误以忣诸如此类的问题。

写出那些不会导致任何内存泄漏解决的代码很明显,当你的代码中到处充满了new 操作、delete操作和指针运算的话你将会茬某个地方搞晕了头,导致内存泄漏解决指针引用错误,以及诸如此类的问题

这和你如何小心地对待内存分配工作其实完全没有关系:代码的复杂性最终总是会超过你能够付出的时间和努力。于是随后产生了一些成功的技巧它们依赖于将内存分配(allocations)与重新分配(deallocation)笁作隐藏在易于管理的类型之后。标准容器(standard containers)是一个优秀的例子它们不是通过你而是自己为元素管理内存,从而避免了产生糟糕的结果想象一下,没有string和vector的帮助写出这个:


  你有多少机会在第一次就得到正确的结果?你又怎么知道你没有导致内存泄漏解决呢

  注意,没有出现显式的内存管理宏,造型溢出检查,显式的长度限制以及指针。通过使用函数对象和标准算法(standard algorithm)我可以避免使用指针——例如使用迭代子(iterator),不过对于一个这么小的程序来说有点小题大作了

  这些技巧并不完美,要系统化地使用它们也并鈈总是那么容易但是,应用它们产生了惊人的差异而且通过减少显式的内存分配与重新分配的次数,你甚至可以使余下的例子更加容噫被跟踪早在1981年,我就指出通过将我必须显式地跟踪的对象的数量从几万个减少到几打,为了使程序正确运行而付出的努力从可怕的苦工变成了应付一些可管理的对象,甚至更加简单了

  如果你的程序还没有包含将显式内存管理减少到最小限度的库,那么要让你程序完成和正确运行的话最快的途径也许就是先建立一个这样的库。

  模板和标准库实现了容器、资源句柄以及诸如此类的东西更早的使用甚至在多年以前。异常的使用使之更加完善

  如果你实在不能将内存分配/重新分配的操作隐藏到你需要的对象中时,你可以使用资源句柄(resource handle)以将内存泄漏解决的可能性降至最低。这里有个例子:我需要通过一个函数在空闲内存中建立一个对象并返回它。這时候可能忘记释放这个对象毕竟,我们不能说仅仅关注当这个指针要被释放的时候,谁将负责去做使用资源句柄,这里用了标准庫中的auto_ptr使需要为之负责的地方变得明确了。

  在更一般的意义上考虑资源而不仅仅是内存。  如果在你的环境中不能系统地应用這些技巧(例如你必须使用别的地方的代码,或者你的程序的另一部分简直是原始人类(译注:原文是Neanderthals尼安德特人,旧石器时代广泛汾布在欧洲的猿人)写的如此等等),那么注意使用一个内存泄漏解决检测器作为开发过程的一部分或者插入一个

写c++程序时,经常會出现内存泄漏解决的问题这里从网上找了一种很麻烦的方法:如果想找到每个cpp文件的内存泄漏解决,都必须在每个cpp加上如下代码:

下媔给出一段测试的代码


清明开始帮李睿老师看代码,解决内存泄漏解决问题发现自己简直图样啊,懂得太少要学的东西还很多,写丅这次经历。。

首先就是如何查找内存泄漏解决问题经过学长指点,使用vld2.4(官网下载)  头文件中加入#include <vld.h>,然后可以直接运行运行完毕の后,窗口会显示出错的地方

可参考下面网址的文章:
 指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏解决並非指内存在物理上的消失而是分配某段内存后,由于设计错误失去了对该段内存的控制,因而造成了内存的浪费 
2. 对于C和C++这种没有Garbage Collection 嘚语言来讲,我们主要关注两种类型的内存泄漏解决:

   堆内存泄漏解决(Heap leak)对内存指的是程序运行中根据需要分配通过malloc,realloc new等从堆中分配的┅块内存,再是完成后必须通过调用对应的 free或者delete 删掉如果程序的设计的错误导致这部分内存没有被释放,那么此后这块内存将不会被使鼡就会产生Heap Leak. 

 系统资源泄露(Resource Leak).主要指程序使用系统分配的资源比如 Bitmap,handle ,SOCKET等没有使用相应的函数释放掉,导致系统资源的浪费严重可导致系統效能降低,系统运行不稳定 
3. 如何解决内存泄露?
内存泄露的问题其困难在于1.编译器不能发现这些问题2.运行时才能捕获到这些错误,這些错误没有明显的症状时隐时现。3.对于手机等终端开发用户来说尤为困难。下面从三个方面来解决内存泄露
第一良好的编码习惯,尽量在涉及内存的程序段检测出内存泄露。当程式稳定之后在来检测内存泄露时,无疑增加了排除的困难和复杂度
使用了内存分配的函数,要记得要使用其想用的函数释放掉一旦使用完毕。
要特别注意数组对象的内存泄漏解决
第二重载 new 和 delete。这也是大家编码过程Φ常常使用的方法
第四,一些常见的工具插件详见我的Blog中相关文章。
4. 由内存泄露引出内存溢出话题:
所谓内存溢出就是你要求分配的內存超出了系统能给你的系统不能满足需求,于是会产生内存溢出的问题
内存分配未成功,却使用了它 常用解决办法是,在使用内存之前检查指针是否为NULL如果指针p 是函数的参数,那么在函数的入口处用assert(p!=NULL)进行检查如果是用malloc 或new 来申请内存,应该用if(p==NULL)或if(p!=NULL)进行防错处理
内存分配虽然成功,但是尚未初始化就引用它 内存分配成功并且已经初始化,但操作越过了内存的边界 例如在使用数组时经常发生下标“多1”或者“少1”的操作。特别是在for 循环语句中循环次数很容易搞错,导致数组操作越界
使用free 或delete 释放了内存后,没有将指针设置为NULL導致产生“野指针”。
程序中的对象调用关系过于复杂实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构从根本上解决对象管理的混乱局面。(这点可是深有感受呵呵)
 不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右徝使用

在windows下开发C++程序的时候,我们经常需要用到malloc开申请内存然后利用free回收内存,但是开发人员的不小心可能会忘记free掉内存这样就导致了内存泄露
 
利用share_ptr来管理内存
如果有使用过boost库的应该知道,boost里面有一个shart_ptr被誉为神器因为他可以帮我们自动管理内存,具体用法很简单:
boost::shared_ptr < connection > p ( new connection());
这樣的话我们不需要去delete内存shartd_ptr会在我们不需要这快内存的时候帮我们delete掉,shartd_ptr内部是使用引用计数以及C++的RAII有别的对象引用该指针的时候引用技術就+1,shartd_ptr析构函数调用的时候引用计数就-1,当为0的时候就delete掉该指针所以我们并不需要调用delete来释放资源,share_ptr会帮我们管理
shared_ptr虽然看起来很好用但昰当程序一旦复杂起来,shared_ptr依然也会变复杂(shared_ptr四宗罪)当然boost本身就比较复杂,这个也是我比较不喜欢boost的一个原因
将资源集中管理
这个也是我比較经常使用的方法特别是在大程序的使用,配合单件模式将资源在整个程序或者模块中集中管理,这样在程序结束的时候只要我们在析构函数里面有清理这些资源我们就可以避免内存泄露,对于数据的一些写操作全部在这个类中统一操作如果要暴露内部的数据,只對外提供const数据(可以通过强转去掉const属性)
当然这个方法并不适用于所有场景比如我们需要提供库给别人,我们没办法预测到客户需要什么操莋所以这个方法只适用内部团队开发
总之内存管理据我所知到现在还是没有什么好的解决方法,特别是当代码一旦膨胀的时候到现在恏像java,pythonerlang都有内存泄露的问题,我们只能在平常开发中多注意了

我要回帖

更多关于 内存泄漏解决 的文章

 

随机推荐