`
阿尔萨斯
  • 浏览: 4184554 次
社区版块
存档分类
最新评论

c/c++内存泄漏检测

 
阅读更多

这几天突然想起了解一下c/c++内存泄漏检测方面的东西,在网上的这方面的介绍也有很多,现在我在这个把我自己感觉有用的在这里总结一下

内存泄漏简介及后果

wikipedia中这样定义内存泄漏:在计算机科学中,内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。

最难捉摸也最难检测到的错误之一是内存泄漏,即未能正确释放以前分配的内存的 bug。 只发生一次的小的内存泄漏可能不会被注意,但泄漏大量内存的程序或泄漏日益增多的程序可能会表现出各种征兆:从性能不良(并且逐渐降低)到内存完全用尽。 更糟的是,泄漏的程序可能会用掉太多内存,以致另一个程序失败,而使用户无从查找问题的真正根源。 此外,即使无害的内存泄漏也可能是其他问题的征兆。

内存泄漏会因为减少可用内存的数量从而降低计算机的性能。最终,在最糟糕的情况下,过多的可用内存被分配掉导致全部或部分设备停止正常工作,或者应用程序崩溃。内存泄漏可能不严重,甚至能够被常规的手段检测出来。在现代操作系统中,一个应用程序使用的常规内存在程序终止时被释放。这表示一个短暂运行的应用程序中的内存泄漏不会导致严重后果。

在Windows 下的检测:

1. 使用crtdbg.h

Windows平台下面Visual Studio 调试器和 C 运行时 (CRT) 库为我们提供了检测和识别内存泄漏的有效方法,原理大致如下:内存分配要通过CRT在运行时实现,只要在分配内存和释放内存时分别做好记录,程序结束时对比分配内存和释放内存的记录就可以确定是不是有内存泄漏。

#define _CRTDBG_MAP_ALLOC                //输出内存泄漏的行号等信息, 这个必须放在crtdbg.h之前
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <crtdbg.h>
void GetMemory(char *p, int num)
{
    p = (char*)malloc(sizeof(char)* num);
}
int main()
{
    char *str = NULL;
    GetMemory(str, 100);

    cout << "Memory leak test!" << endl;
    _CrtDumpMemoryLeaks();

    return 0;
}

输出结果:

Detected memory leaks!
Dumping objects ->
{152} normal block at 0x00FD4098, 4 bytes long.
Data: <    > CD CD CD CD
  e : \my projects\cpp\hellovs2013\hellovs2013\helloworld.cpp(20) : {151} normal block at 0x00FDA5A0, 100 bytes long.
  Data : <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
         Object dump complete.
         程序“[5472] HelloVs2013.exe”已退出,返回值为 0 (0x0)。


crtdbg.h有个不好的就是虽然也能检测到new 操作法造成的泄漏,但是不能定位泄漏的位置。

定位具体的内存泄漏地方

1 _CrtMemState s1, s2, s3;

若要在给定点对内存状态拍快照,请向_CrtMemCheckpoint函数传递_CrtMemState结构。 该函数用当前内存状态的快照填充此结构:

1 _CrtMemCheckpoint( &s1 );

通过向_CrtMemDumpStatistics函数传递_CrtMemState结构,可以在任意点转储该结构的内容:

1 _CrtMemDumpStatistics( &s1 );

若要确定代码中某一部分是否发生了内存泄漏,可以在该部分之前和之后对内存状态拍快照,然后使用_CrtMemDifference比较这两个状态:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

#include <iostream>
using namespace std;
_CrtMemState s1, s2, s3;
void GetMemory(char *p, int num)
{
    p = (char*)malloc(sizeof(char)* num);
}
int main(int argc, char** argv)
{
    _CrtMemCheckpoint(&s1);
    char *str = NULL;
    GetMemory(str, 100);
    _CrtMemCheckpoint(&s2);
    if (_CrtMemDifference(&s3, &s1, &s2))
        _CrtMemDumpStatistics(&s3);
    cout << "Memory leak test!" << endl;
    _CrtDumpMemoryLeaks();
    return 0;
}

调试时,程序输出如下结果:

image

这说明在s1和s2之间存在内存泄漏!!!如果GetMemory不是在s1和s2之间调用,那么就不会有信息输出。


Linux平台下的内存泄漏检测

在上面我们介绍了,vs中在代码中“包含crtdbg.h,将mallocfree函数映射到它们的调试版本,即_malloc_dbg_free_dbg,这两个函数将跟踪内存分配和释放。 此映射只在调试版本(在其中定义了_DEBUG)中发生。 发布版本使用普通的mallocfree函数。”即为malloc和free做了钩子,用于记录内存分配信息。

Linux下面也有原理相同的方法——mtrace,http://en.wikipedia.org/wiki/Mtrace。方法类似,我这就不具体描述,参加给出的链接。这节我主要介绍一个非常强大的工具valgrind。如下图所示:

image

如上图所示知道:

==6118== 100 bytes in 1 blocks are definitely lost in loss record 1 of 1
==6118== at 0x4024F20: malloc (vg_replace_malloc.c:236)
==6118== by 0x8048724: GetMemory(char*, int) (in /home/netsky/workspace/a.out)
==6118== by 0x804874E: main (in /home/netsky/workspace/a.out)

是在main中调用了GetMemory导致的内存泄漏,GetMemory中是调用了malloc导致泄漏了100字节的内存。

Things to notice:
• There is a lot of information in each error message; read it carefully.
• The 6118 is the process ID; it’s usually unimportant.
• The first line ("Heap Summary") tells you what kind of error it is.
• Below the first line is a stack trace telling you where the problem occurred. Stack traces can get quite large, and be
confusing, especially if you are using the C++ STL. Reading them from the bottom up can help.

• The code addresses (eg. 0x4024F20) are usually unimportant, but occasionally crucial for tracking down weirder
bugs.

The stack trace tells you where the leaked memory was allocated. Memcheck cannot tell you why the memory leaked,
unfortunately. (Ignore the "vg_replace_malloc.c", that’s an implementation detail.)
There are several kinds of leaks; the two most important categories are:
• "definitely lost": your program is leaking memory -- fix it!
• "probably lost": your program is leaking memory, unless you’re doing funny things with pointers (such as moving
them to point to the middle of a heap block)

Valgrind的使用请见手册http://valgrind.org/docs/manual/manual.html


2.使用VLD工具

下载vld:http://vld.codeplex.com/releases/view/82311

http://www.codeproject.com/tools/visualleakdetector.asp

使用 解压之后得到vld.h, vldapi.h, vld.lib, vldmt.lib, vldmtdll.lib, dbghelp.dll等文件。将.h文件和.lib文件拷贝到你要检测的工程文件所在的目录里(只针对此工程),将dbghelp.dll拷贝到你的程序的运行目录下。

用法:在包含入口函数的.cpp文件中加入语句#include "vld.h" #pragma comment(lib, "vld.lib")即可。
编译正确后,在debug方式下运行:查看VC的输出信息:
有内存泄露显示:"WARNING: Visual Leak Detector detected memory leaks!"
没有内存泄露,此输出的信息为:"No memory leaks detected."

//#define _CRTDBG_MAP_ALLOC
#include <stdio.h>
#include <string.h>
#include <iostream>
//#include <crtdbg.h>

#include "vld.h"
#pragma comment(lib, "vld.lib")

using std::cout;
using std::endl;
void GetMemory(char *p, int num)
{
    p = (char*)malloc(sizeof(char)* num);
    int* ip = new int;
}

int main()
{
    char *str = NULL;
    GetMemory(str, 100);
    cout << "Memory leak test!" << endl;
    //_CrtDumpMemoryLeaks();
    return 0;
}
输出:

Visual Leak Detector Version 1.0 installed (multithreaded DLL).
WARNING: Visual Leak Detector detected memory leaks!
---------- Block 153 at 0x01165528: 4 bytes ----------
Call Stack:
0x0F39D626 (File and line number not available): free_dbg
0x0F39DBCD (File and line number not available): msize_dbg
0x0F39DB7A (File and line number not available): msize_dbg
0x0F39E5A9 (File and line number not available): malloc
0x0F38C26F (File and line number not available): operator new
e:\my projects\cpp\hellovs2013\hellovs2013\helloworld.cpp (21): GetMemory
e:\my projects\cpp\hellovs2013\hellovs2013\helloworld.cpp (30): main
f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (626): __tmainCRTStartup
f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (466): mainCRTStartup
0x770B495D (File and line number not available): BaseThreadInitThunk
0x778398EE (File and line number not available): RtlInitializeExceptionChain
0x778398C4 (File and line number not available): RtlInitializeExceptionChain
Data:
CD CD CD CD ........ ........
---------- Block 152 at 0x0116FE88: 100 bytes ----------
Call Stack:
0x0F39D626 (File and line number not available): free_dbg
0x0F39DBCD (File and line number not available): msize_dbg
0x0F39DB7A (File and line number not available): msize_dbg
0x0F39E5A9 (File and line number not available): malloc
e:\my projects\cpp\hellovs2013\hellovs2013\helloworld.cpp (20): GetMemory
e:\my projects\cpp\hellovs2013\hellovs2013\helloworld.cpp (30): main
f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (626): __tmainCRTStartup
f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (466): mainCRTStartup
0x770B495D (File and line number not available): BaseThreadInitThunk
0x778398EE (File and line number not available): RtlInitializeExceptionChain
0x778398C4 (File and line number not available): RtlInitializeExceptionChain
Data:
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD ........ ........
CD CD CD CD ........ ........
Visual Leak Detector detected 2 memory leaks.
Visual Leak Detector is now exiting.




分享到:
评论

相关推荐

    C/C++ 内存泄露检测工具 memwatch2.69

    C/C++ 内存泄露检测工具 memwatch,下载

    介绍几款 C/C++内存泄漏检测工具.帮程序员擦屁股用

    介绍几款 C/C++内存泄漏检测工具Check Memory Leak.帮程序员擦屁股用

    C/C++程序内存泄漏检测

    C/C++程序内存泄漏检测,在编程中容易忽略的问题

    windows下c++内存泄露检测工具使用方

    windows下c++内存泄露检测工具使用方windows下c++内存泄露检测工具使用方

    C++内存泄露检测器

    C++ 内存 泄露 检测器 对于一个c/c++程序员来说,内存泄漏是一个常见的也是令人头疼的问题。已经有许多技术被研究出来以应对这个问题

    C/C++程序内存泄漏检测算法的研究

    但是C/C++语言编译器GCC和Clang都不提供内存安全检测,导致开发人员使用C/C++语言编写的项目可能存在内存泄漏的风险。文章介绍了改进指针算法和shared_ptr源码,分析了它们检测内存泄漏的方式,最后指出该类算法的...

    Linux 平台中调试 C-C++ 内存泄漏方法

    在 Linux 平台中调试 C-C++ 内存泄漏方法

    内存泄漏检测工具(tMemMonitor)

    运行时C/C++内存泄漏检测工具 在被监控程序退出时检测出所有没有指针指向的内存块。 是一款运行时C/C++内存泄漏分析工具,其检测结果专业、准确,操作却极其简单,可以帮助C/C++程序员迅速解决内存泄漏。TMM中引入GC...

    浅谈C/C++内存泄露及其检测工具

    Smart Pointer,Garbage Collection等。Smart Pointer技术比较成熟,STL中已经包含支持...Garbage Collection技术在Java中已经比较成熟,但是在c/c++领域的发展并不顺畅,虽然很早就有人思考在C++中也加入GC的支持。

    浅谈C_C++内存泄漏及其检测工具

    浅谈C_C++内存泄漏及其检测工具, 对C/C++的内存泄露做了简洁的介绍, 并介绍了检测方法和工具.

    浅谈C/C++内存泄漏及其检测工具

    对于一个c/c++程序员来说,内存泄漏是一个常见的也是令人头疼的问题。已经有许多技术被研究出来以应对这个问题,比如SmartPointer,GarbageCollection等。SmartPointer技术比较成熟,STL中已经包含支持SmartPointer...

    最好用的内存泄漏分析工具 ------ tMemMonitor (TMM)

    tMemMonitor(TMM)是一款运行时C/C++内存泄漏分析工具,其检测结果专业、准确,操作却极其简单,可以帮助C/C++程序员迅速解决内存泄漏。TMM中引入GC机制,内存泄露检测准确率可达100%,无需内存快照,不影响目标...

    C和C++内存管理资料(包括内存管理-内存泄漏-内存调试-内存检测方法)

    本人收集的关于内存方面的经典文档,压缩包里涵盖了目前基本所有的c/c++关于内存的文章,C和C++内存管理资料(包括内存管理-内存泄漏-内存调试-内存检测方法) 还有一个文档介绍电网的调试技巧

    vld2.5 C++内存泄露检测工具

    VLD是一款用于VisualC++的免费内存泄漏检查工具。可以在codeproject.com网站上找到,相比其它的内存泄漏哦给你根据,他在检查内存泄漏的同事,还具有如下特点: 1) 可以得到内存泄漏点的调用堆栈,如果可以的话,...

    C/C++内存泄漏及检测

     难捉摸也难检测到的错误之一是内存泄漏,即未能正确释放以前分配的内存的 bug。 只发生一次的小的内存泄漏可能不会被注意,但泄漏大量内存的程序或泄漏日益增多的程序可能会表现出各种征兆:从性能不良(并且逐渐...

    浅谈CC++内存泄漏及其检测工具

    浅谈C/C++内存泄漏及其检测工具2006-04-03 09:00 作者: 出处: 温馨小屋 责任编辑:&gt;方舟 对于一个c/c++程序员来说,内存泄漏是一个常见的也是令人头疼的问题。已经有许多技术被研究出来以应对这个问题,比如Smart...

    C/C++源代码静态检测系统的设计和实现

    为了检测出C/C++源代码程序中常见的运行时错误,设计了一个静态检测系统。...通过检测程序对结点的属性值的分析,能够检测出C/C++源代码程序中出现的数组越界、指针错误、字符串函数错误,内存泄露等问题。

    vc内存泄露检测

    C/C++ 编程语言的最强大功能之一便是其动态... 幸运的是,Visual Studio 调试器和 C 运行时 (CRT) 库为我们提供了检测和识别内存泄漏的有效方法。下面请和我一起分享收获——如何使用 CRT 调试功能来检测内存泄漏?

    C++内存管理.doc

    2.3浅谈C/C++内存泄漏及其检测工具 2.3.1 内存泄漏的定义 2.3.2 内存泄漏的发生方式 2.3.3 检测内存泄漏 2.3.3.1 VC下内存泄漏的检测方法 2.3.3.2 使用BoundsChecker检测内存泄漏 2.3.3.3 使用Performance Monitor...

Global site tag (gtag.js) - Google Analytics