C++中内存泄漏的原因几种情况

Linux下几款C++程序中的内存泄露检查工具_linux教程-织梦者
当前位置:&>&&>& > Linux下几款C++程序中的内存泄露检查工具
Linux下几款C++程序中的内存泄露检查工具
Linux下编写C或者C++程序,有很多工具,但是主要编译器仍然是gcc和g++。最近用到STL中的List编程,为了检测写的代码是否会发现内存泄漏,了解了一下相关的知识。
所有使用动态内存分配(dynamic memory allocation)的程序都有机会遇上内存泄露(memory leakage)问题,在Linux里有三种常用工具来检测内存泄露的情況,包括:
参见 http://elinux.org/Memory_Debuggers
一个强大开源的程序检测工具
GNU扩展, 用来跟踪malloc, mtrace为内存分配函数(malloc, realloc, memalign, free)安装hook函数
用于检查C/C++内存泄露(leak)的工具,即检查是否存在直到程序运行结束还没有释放的内存,以一个运行库的方式发布
和dmalloc一样,它能检测未释放的内存、同一段内存被释放多次、位址存取错误及不当使用未分配之内存区域
一个跨平台的 C++ 内存泄漏检测器
Electric Fence
为了方便测试,,我们编写了一个简单的程序, 循环10次每次申请了一个100个字节的单元, 但是却不释放
valgrind介绍
是不是说没有一种内存检查工具能够在Linux使用呢,也不是,像开源的valgrind工具还是相当不错的
Memcheck。这是valgrind应用最广泛的工具,一个重量级的内存检查器,能够发现开发中绝大多数内存错误使用情况,比如:使用未初始化的内存,使用已经释放了的内存,内存访问越界等。这也是本文将重点介绍的部分。
Callgrind。它主要用来检查程序中函数调用过程中出现的问题。
Cachegrind。它主要用来检查程序中缓存使用出现的问题。
Helgrind。它主要用来检查多线程程序中出现的竞争问题。
Massif。它主要用来检查程序中堆栈使用中出现的问题。
Extension。可以利用core提供的功能,自己编写特定的内存调试工具
Valgrind简单用法
Unix下C程序内存泄漏检测工具Valgrind安装与使用
valgrind 的使用简介
应用 Valgrind 发现 Linux 程序的内存问题
如何使用Valgrind memcheck工具进行C/C++的内存泄漏检测
到下载地址)下载最新版的valgrind,按照里面的README提示,安装后就可以使用这个工具来检测内存泄露和内存越界等
/configure
sudo make install
当然也可以使用发行版的自带的源中安装
sudo apt install valgrind
这是一个没有界面的内存检测工具,安装后,输入 valgrind ls -l 验证一下该工具是否工作正常(这是README里面的方法,实际上是验证一下对ls -l命令的内存检测),如果你看到一堆的信息说明你的工具可以使用了。
Valgrind工具包包含多个工具,如Memcheck,Cachegrind,Helgrind, Callgrind,Massif。
最常用的工具,用来检测程序中出现的内存问题,所有对内存的读写都会被检测到,一切对malloc()/free()/new/delete的调用都会被捕获。所以,Memcheck 工具主要检查下面的程序错误
使用未初始化的内存
Use of uninitialised memory
使用已经释放了的内存
Reading/writing memory after it has been free’d
使用超过 malloc分配的内存空间
Reading/writing off the end of malloc’d blocks
对堆栈的非法访问
Reading/writing inappropriate areas on the stack
申请的空间是否有释放
Memory leaks – where pointers to malloc’d blocks are lost forever
malloc/free/new/delete申请和释放内存的匹配
Mismatched use of malloc/new/new [] vs free/delete/delete []
src和dst的重叠
Overlapping src and dst pointers in memcpy() and related functions
这些问题往往是C/C++程序员最头疼的问题,Memcheck在这里帮上了大忙。
和gprof类似的分析工具,但它对程序的运行观察更是入微,能给我们提供更多的信息。和gprof不同,它不需要在编译源代码时附加特殊选项,但加上调试选项是推荐的。Callgrind收集程序运行时的一些数据,建立函数调用关系图,还可以有选择地进行cache模拟。在运行结束时,它会把分析数据写入一个文件。callgrind_annotate可以把这个文件的内容转化成可读的形式。
Cachegrind
Cache分析器,它模拟CPU中的一级缓存I1,Dl和二级缓存,能够精确地指出程序中cache的丢失和命中。如果需要,它还能够为我们提供cache丢失次数,内存引用次数,以及每行代码,每个函数,每个模块,整个程序产生的指令数。这对优化程序有很大的帮助。
它主要用来检查多线程程序中出现的竞争问题。Helgrind寻找内存中被多个线程访问,而又没有一贯加锁的区域,这些区域往往是线程之间失去同步的地方,而且会导致难以发掘的错误。Helgrind实现了名为“Eraser”的竞争检测算法,并做了进一步改进,减少了报告错误的次数。不过,Helgrind仍然处于实验阶段。
堆栈分析器,它能测量程序在堆栈中使用了多少内存,告诉我们堆块,堆管理块和栈的大小。Massif能帮助我们减少内存的使用,在带有虚拟内存的现代系统中,它还能够加速我们程序的运行,减少程序停留在交换区中的几率。
此外,lackey和nulgrind也会提供。Lackey是小型工具,很少用到;Nulgrind只是为开发者展示如何创建一个工具
Valgrind不检查静态分配数组的使用情况
Valgrind占用了更多的内存–可达两倍于你程序的正常使用量
如果你用Valgrind来检测使用大量内存的程序就会遇到问题,它可能会用很长的时间来运行测试
g++ -g -o leak leak.c
被检测程序加入 –g
-fno-inline 编译选项保留调试信息, 否则后面的valgrind不能显示到出错行号。
valgrind被设计成非侵入式的,它直接工作于可执行文件上,因此在检查前不需要重新编译、连接和修改你的程序。要检查一个程序很简单,只需要执行下面的命令就可以了。
valgrind --tool=tool_name program_name
比如我们要对ls -l命令做内存检查,只需要执行下面的命令就可以了
valgrind --tool=memcheck ls -l
如果不知道有哪些参数, 可以先输入valgrind –tool=, 然后狂按两次tab, 会输出linux系统的只能提示, 同样,如果你输入了valgrind –tool=mem再狂按两次tab,linux系统会为你自动补全
使用valgrind检测Memcheck
下面我们就可以用valgrind对我们的程序检测leak
valgrind --tool=memcheck --leak-check=full --show-reachable=yes --trace-children=yes
其中–leak-check=full 指的是完全检查内存泄漏,
–show-reachable=yes是显示内存泄漏的地点,
–trace-children=yes是跟入子进程。
当程序正常退出的时候valgrind自然会输出内存泄漏的信息原理:
mtrace检测内存泄露
mtrace简介
在一般的linux发行版中,有一个自带的工具可以很方便的替你完成这些事,这个工具就是mtrace.
mtrace其实是GNU扩展函数,用来跟踪malloc。
mtrace为内存分配函数(malloc, realloc, memalign, free)安装hook函数。这些hook函数记录内存的申请和释放的trace信息。
在程序中,这些trace信息可以被用来发现内存泄漏和释放不是申请的内存。
当调用mtrace,mtrace会检查环境变量MALLOC_TRACE。该环境变量应该包含记录trace信息的文件路径。如果文件可以被成功打开,它的大小被截断为0。
如果MALLOC_TRACE没有设置,或者设置的文件不可用或者不可写,那么将不会安装hook函数,mtrace不生效。
详细说明可参考man page:man 3 mtrace
mtrace使用
mtrace能监测程序是否内存泄露
在程序的起始处包含头文件
#include &mcheck.h&
更改环境变量:export
MALLOC_TRACE=”mtrace.out”可以加入如下代码
setenv("MALLOC_TRACE", "mtrace.out", 1);
调用函数mtrace()
编译程序带上 -g 选项
gcc -g -c leak_mtrace.c -o leak_mtrace.o
-std=gnu9x -Wall
运行程序一次,尽量调用所有程序内的函数。这时调试信息就已经被写入我们指定的mtrace.out文件中
./leak_mtrace
mtrace a.out
mtrace.out查看内存监测情况
mtrace a.out
mtrace.out
dmalloc是一种用于检查C/C++内存泄露(leak)的工具,即检查是否存在直到程序运行结束还没有释放的内存,并且能够精确指出在哪个源文件的第几行。
以上就是Linux下几款C++程序中的内存泄露检查工具的全文介绍,希望对您学习和使用linux系统开发有所帮助.
这些内容可能对你也有帮助
更多可查看linux教程列表页。
猜您也会喜欢这些文章c++在哪些情况下会产生内存泄露_百度知道
c++在哪些情况下会产生内存泄露
我有更好的答案
有开辟,没释放;或者 释放不完全。不干净。 没释放:有new,没有delete。有malloc没有free;释放不干净:EX: char* a = new char [10];
delete[]a;
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。实际工作中的 C++ 项目都是没有内存泄漏的么? - 知乎363被浏览<strong class="NumberBoard-itemValue" title="4分享邀请回答28014 条评论分享收藏感谢收起135 条评论分享收藏感谢收起没有更多推荐了,
不良信息举报
举报内容:
C++中内存泄漏的几种情况
举报原因:
原文地址:
原因补充:
最多只允许输入30个字
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!Visual C++ ;&#30340;&#20869;&#23384;&#20998;&#26512; &#8211; C++
This site uses cookies for analytics, personalized content and ads. By continuing to browse this site, you agree to this use.
[原文发表地址]
[原文发表时间]
正如在之前的中公布的,Visual Studio 2015中发布了一系列新的内存分析工具,帮助定位和解决您应用程序中的内存问题。这个新的调试实时分析器在您的调试阶段运行,您可以在任何时间捕获快照,例如在一个断点上,您也可以在任何暂停状态查看堆内容。当您在想要分析您的应用程序堆状态时,此工具提供更精确和灵活的体验。
在VS2015中第一次启动调试器时,呈现在您面前的是新的,它能让您看到您正运行的应用程序调试器事件、内存使用率,以及CPU利用率。您可利用内存使用率图来监控调试过程中的总体内存消耗,当您需要更多信息时,您也可以开启堆数据分析并捕获快照来得到更为详细的内存分配分析。
内存分配跟踪及总览
内存分析器可以在应用程序运行中实时收集分配事件数据,然后将这些数据以类型信息形式映射到您的PDB中。由于对VS2015 (v140) 编译器的技术性依赖,类型信息只显示那些使用此版本或更高版本编译器来编译的目标。在一个应用程序调试的过程中收集内存分配事件数据是有内在开销的,因此快照功能默认是关闭的。如要激活堆快照,在诊断工具窗口中打开内存使用率分页并点击堆分析按钮,按钮图标就变为黄色。自VS2015 Update 1 CTP预览版起,堆分析的开启可以无需重启调试器。发生在开启快照前的分配将不会被跟踪,因此您要确保在开启堆分析之后您有一个合适的基线可以重启调试器,或者在设计阶段按F11来开始调试和跳出第一条指令。注意如果您关闭堆快照功能,此项设置将会在终止现有的调试会话之后起作用。
一旦开启快照功能,快照将会在点击&捕获快照&按钮时获取并显示在快照表中。每张快照列出了捕获快照时的执行时间、分配总数和千字节的堆大小。您可以通过点击每一列(内存分配数或堆大小)左边的总数链接打开这个堆快照的完整视图。选择每一列右边的+/-链接可以看到快照差异,并且打开的快照是以此数值排序显示的。
当您打开一张快照,最初是以在内存中包含的所有对象类型列表显示的。每一个数据类型的总数和内存占用是以降序默认列出的。您可以通过点击相应列的顶部单元格来实现以对象类型名称、数量或大小来排序。在类型视图中不确定类型是默认隐藏的,但是它可以通过点击查询框左边的过滤器图标并取消&隐藏不确定类型&被轻松地显示。
双击或者右击一行,选择一个类型&查看实例&,您就可以导航到这个类型的实例并查看单个对象以及它们完整的分配调用堆栈。选择调用堆栈的一行,它将链接到对应的源代码上。您可以通过悬停在一行实例上来激活调试数据提示,这样就能很方便地查看对象的内容,如下在CTrackerChannel 这个实例上的演示:
在类型页中视图选择框中选择&堆栈&,就可以轻松地通过堆栈帧查看调用树了。您可以通过选择窗口右上角的按钮来根据调用和被调用收集堆栈帧。所有的分配都源于被标记为[self]的当前函数。您可以用右上角的搜索框搜索调用堆栈,很容易地就会搜索到您想找的帧:
从调用树中选择一个堆栈帧,源于此堆栈帧的所有分配和他们的类型就会出现在窗口下部的面板中。展开分配,它的分配调用堆栈将显示在下面。
支持定制分配器
发布的Windows 附带一个ETW提供者,它能在Windows堆中进行事件跟踪分配和重新分配。我们可以把提供者配置成:每个事件包含一个堆栈跟踪。标签__declspec(allocator)可以使编译器确定一个函数调用是对一个分配器的调用,也就是说,一个函数返回新的堆分配内存。在每一次调用分配器函数时,调用点的地址、调用指令的大小和新对象的typeid发送到一个包含在PDB文件里的新的S_HEAPALLOCSITE符号 。当Windows堆代码对一个分配发出一个带有调用堆栈的ETW事件时 ,内存工具在调用堆栈中寻找一个与S_HEAPALLOCSITE符号相匹配的返回地址。符号中的类型typeid决定了分配的运行时类型。
在CRT(新建,分配内存,&&)和Windows SDK中的分配器已经在源代码层被标记,这样它们的分配数据可以被捕获并映射到相应的符号。 任何代码想要支持在堆分析期间显示分配的类型信息, 需要v140编译器(或者更高的版本)来编译 。为了提高内存分析的准确性,可以利用__declspec(allocator),确保任何函数返回一个指向新分配的堆内存的指针,正如 myMalloc(size_t size)这个例子:
__declspec(allocator) void* myMalloc(size_t size);
VS2015 Update 1 CTP上的新功能
支持&附加到进程&分析
版本现在具备附加到一个正在运行的进程以及激活对那个进程进行本地堆分析的能力。如果您怀疑一个内存泄漏是在执行后期发生的,在您调试程序问题之前,您可以回避分配跟踪的性能损失的问题。在一个正在运行的进程上激活堆分析的进程同以上一样。一旦分析被激活,这一设置将贯穿于整个目标进程的调试会话始终。
支持远程分析
Visual Studio 的CTP版本同样具备当远程调试一个应用程序时,分析这个应用程序,甚至附加到远程进程分析的能力。这使您可以在超越您开发环境之外的设备上,进行内存使用情况的监控,就像在本地调试会话中一样捕获堆快照。
Archives &(4)

我要回帖

更多关于 java中内存泄漏 的文章

 

随机推荐