C++程序如何精确查找内存泄漏

一、前言

在Linux平台上有valgrind可以非常方便的帮助我们定位内存泄漏,因为Linux在开发领域的使用场景大多是跑服务器,再加上它的开源属性,相对而言,处理问题容易形成“统一”的标准。而在Windows平台,服务器和客户端开发人员惯用的调试方法有很大不同。下面结合我的实际经验,整理下常见定位内存泄漏的方法。

注意:我们的分析前提是Release版本,因为在Debug环境下,通过VLD这个库或者CRT库本身的内存泄漏检测函数能够分析出内存泄漏,相对而言比较简单。而服务器有很多问题需要在线上并发压力情况下才出现,因此讨论Debug版调试方法意义不大。

二、对象计数

方法:在对象构造时计数++,析构时--,每隔一段时间打印对象的数量

优点:没有性能开销,几乎不占用额外内存。定位结果精确。

缺点:侵入式方法,需修改现有代码,而且对于第三方库、STL容器、脚本泄漏等因无法修改代码而无法定位。

三、重载new和delete

方法:重载new/delete,记录分配点(甚至是调用堆栈),定期打印。

优点:没有看出

缺点:侵入式方法,需将头文件加入到大量源文件的头部,以确保重载的宏能够覆盖所有的new/delete。记录分配点需要加锁(如果你的程序是多线程),而且记录分配要占用大量内存(也是占用的程序内存)。

四、Hook Windows系统API

方法:使用微软的detours库,hook分配内存的系统Api:HeapAlloc/HeapRealloc/HeapFree(new/malloc的底层调用),记录分配点,定期打印。

优点:非侵入式方法,无需修改现有文件(hook api后,分配和释放走到自己的钩子函数中),检查全面,对第三方库、脚本库等等都能统计到。

缺点:记录内存需要占用大量内存,而且多线程环境需要加锁。

五、使用DiagLeak检测

微软出品的内存泄漏分析工具,原理同hookapi方式。配合LDGraph可视化展示内存分配数据,更方便查找泄漏。

在IDE工程选项里面配置Release版本也生成调试信息,发布时,将pdb文件和exe文件一起发布。

程序运行后,打开LeakDiag,设置Symbol path

定期Log下目标进程的内存分配情况,通过LDGraph打印分配增长情况,来发现内存泄漏。

优点:同hookapi方法,非侵入式修改,无需做任何代码改动。跟踪全面。可视化分析堆栈一览无余!

缺点:对性能有影响,hook分配加锁,遍历堆栈。但是不会占用目标进程的自身内存。

六、总结

对于线上生产环境,建议大对象用计数来判断,定位快速准确,几乎无性能开销。在对外测试阶段,使用LeakDiag辅助分析,因为此时并发压力还不是太大,性能开销还是可以承受。在线上大规模应用阶段,通过HookApi的方法,结合GM指令控制部分时间段的检测,这样可以把对玩家的影响(服务器性能下降导致延迟)降到最低。

以上方法,我将后续的博客中逐一详细介绍,文中提到到detours库和LeakDiag工具,想了解的朋友,可以上codeprojet上搜索下相关介绍,如果要上google查找资料,也可以上这里。如果大家有新方法也可留言讨论,我们共同完善这一系列的介绍文章。

时间: 2024-10-12 14:05:39

C++程序如何精确查找内存泄漏的相关文章

valgrind查找内存泄漏问题

程序运行一晚上,早晨一看,出现了Killed信息,然后在网上查找一下,说应该是程序占用资源过高,被系统终止了. 然后我又运行一段时间,看内存果然涨到了使用率40%多,然后就开始查找内存泄漏的问题,由于程序本来就不大,我手动 在代码中找new和malloc,然后又找delete和free,找到了两处,然后修正了. 但是运行一段时间还是在涨,虽然涨的慢了,但是还是有问题,于是就想到了用valgrind.\ 第一次使用的时候是用的 valgrind + 程序,这样运行的,但是发现信息好像太少了,于是改

c/c++使用 CRT 库查找内存泄漏

前言: 内存泄漏,即未能正确释放以前分配的内存,是 C/C++ 应用程序中最难以捉摸也最难以检测到的 Bug 之一. 最初少量内存泄漏可能不引人注目,但随着时间的推移,内存泄漏越来越多,就会出现一些征兆,包括性能下降,在应用程序内存不足时发生崩溃. 更严重的是,占用了所有可用内存的泄漏应用程序可能会导致其他应用程序崩溃,从而无法确定问题出在哪个应用程序. 即使看似无害的内存泄漏也可能说明存在其他问题应当纠正. 借助 Visual Studio 调试器和 C 运行时 (CRT) 库,可以检测和识别

VC++中查找内存泄漏最简单的方法

1.在整个程序的代码开头(比如stdafx.h文件最前边)加上: #define  CRTDBG_MAP_ALLOC   #include  <stdlib.h> #include  <crtdbg.h> 2.在出口(比如~CApp())加上: _CrtDumpMemoryLeaks(); 注意:若添加的位置不正确,得到的结果可能没有意义.

了解 JavaScript 应用程序中的内存泄漏

简介 当处理 JavaScript 这样的脚本语言时,很容易忘记每个对象.类.字符串.数字和方法都需要分配和保留内存.语言和运行时的垃圾回收器隐藏了内存分配和释放的具体细节. 许多功能无需考虑内存管理即可实现,但却忽略了它可能在程序中带来重大的问题.不当清理的对象可能会存在比预期要长得多的时间.这些对象继续响应事件和消耗资源.它们可强制浏览器从一个虚拟磁盘驱动器分配内存页,这显著影响了计算机的速度(在极端的情形中,会导致浏览器崩溃). 内存泄漏指任何对象在您不再拥有或需要它之后仍然存在.在最近几

java内存泄漏查找

java由于拥有自动垃圾回收机制,所以一般情况下,我们不需要考虑内存泄漏的问题.jvm会自动收回无用的对象.所谓无用的对象,表示你的程序不可能再访问的对象. 但是,有一种情况必须考虑,就是要防止容器(List,Map等)内的对象无限增大.因为对象存贮在容器中,会被容器引用,从而如果容器的有效,容器内的对象就不会释放. 一旦真的出现内存泄漏,随着时间的推移,java程序逐渐增大内存消耗,最后出现OutOfMemory异常而终止. 如何查找内存泄漏? 这种情况下,一般需要找到内存泄漏的对象.也就是要

Android应用程序内存泄漏介绍

Android应用程序内存泄漏介绍 内存泄漏和内存溢出的区别 内存溢出(out of memory)是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory.比如在我们每个Android程序在运行时系统都会给程序分配一个一定的内存空间,当程序在运行中需要的内存超出这个限制就会报内存溢出(out of memory). 内存泄漏(memory leak)是指程序在申请内存后,无法释放已申请的内存空间.多次内存无法被释放,程序占用的内存会一直增加,直到超过系统的内存限制报内存

Android内存泄漏查找和解决

Android内存泄漏查找和解决 目录: 内存泄漏的概念 一个内存泄漏的例子 Java中"失效"的private修饰符 回头看内存泄漏例子泄漏的重点 强引用与弱引用 解决内部类的内存泄漏 Context造成的泄漏 使用LeakCanary工具查找内存泄漏 总结 一.内存泄漏概念 1.什么是内存泄漏? 用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元.直到程序结束.即所谓的内存泄漏. 其实说白了就是该内存空间使用完毕之后未回收 2.内存泄漏会导致的问题 内

C/C++应用程序内存泄漏检查统计方案

一.前绪 C/C++程序给某些程序员的几大印象之一就是内存自己管理容易泄漏容易崩,笔者曾经在一个产品中使用C语言开发维护部分模块,只要产品有内存泄漏和崩溃的问题,就被甩锅“我的程序是C#开发的内存都是托管的,C++那边也没有内存(庇护其好友),肯定是C这边的问题”(话说一个十几年的程序员还停留在语言层面不觉得有点low吗),笔者毕业不到一年,听到此语心里一万头草泥马奔腾而过,默默地修改了程序,注意不是修改bug(哈哈),而是把所有malloc和free都替换成了自定义宏MALLOC和FREE,d

(转)从内存管 理、内存泄漏、内存回收探讨C++内存管理

http://www.cr173.com/html/18898_all.html 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题,C++高手从中获得了更好的性能,更大的自由,C++菜鸟的收获则是一遍一遍的检查代码和对 C++的痛恨,但内存管理在C++中无处不在,内存泄漏几乎在每个C++程序中都会发生,因此要想成为C++高手,内存管理一关是必须要过的,除非放弃 C++,转到Java或者.NET,他们的内存管理基本是自动的,当然你也放弃了自由和对内存的支配权,还放弃了C++超绝的性能