Windows平台上C++开发内存泄漏检查方法

简介: 充分的利用调试工具可以非常方便地避免内存泄漏问题。       这里介绍两种方法,互为补充,第一种是VC编译器提供的方法,第二种是专用的内存泄漏检查工具Memmory Validator。这两种方法的基本原理是一样的:内存分配要通过CRT在运行时实现,只要在分配内存和释放内存时分别做好记录,程序结束时对比分配内存和释放内存的记录就可以确定是不是有内存泄漏。

 充分的利用调试工具可以非常方便地避免内存泄漏问题。

 

    这里介绍两种方法,互为补充,第一种是VC编译器提供的方法,第二种是专用的内存泄漏检查工具Memmory Validator。这两种方法的基本原理是一样的:内存分配要通过CRT在运行时实现,只要在分配内存和释放内存时分别做好记录,程序结束时对比分配内存和释放内存的记录就可以确定是不是有内存泄漏。其中,第一种方法重载了new操作符,第二种方法是替换了CRT运行时库,在用户程序与运行库之间加了一层,用于记录内存分配情况。两种方法的不同是前者是在编译时完成的,分析内存情况的代码编译到执行文件中,用于程序的debug版本,后一种对编译过程没有影响,在执行过程中截留与CRT的交互信息。

 

     第一种方法是MSDN中介绍了,在需要检查内存分配情况的cpp文件中引用<stdlib.h><ctrdbg.h>两个头文件,放于最头部,再用宏代换的方法用重载后的new操作符代替原来的new操作符,如下列代码所示,在程序退出的位置调用_CrtDumpMemoryLeaks()输出全部没有释放的内存内容,及申请这些内存的源代码位置,非常便于调试。

 

     但这种方法有缺陷,_CrtDumpMemoryLeaks()必须在main()函数结束之前调用,所以main()函数中的栈对象还没有析构,会被当做内存泄漏,如下面代码中的NewClass类的对象,实际是没有问题的。另外就是不同编译器实现非ASCII码字符时可能会有所不同,如下面代码中的汉字串都被视为内存泄漏。

#include <stdlib.h>

#include <crtdbg.h>

 

#include <string>

#include <iostream>

#include <vector>

using namespace std;

 

#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)

#define new DEBUG_NEW

 

struct AlertDescriptionString

{

     unsigned int ID;

     string Name;

     string Desp;

};

 

const AlertDescriptionString String[] =

{

    {0,"AAA","BBBB"},

     // memory leak count by _CRTDBG_MAP_ALLOC

    {1,"CCC","__XXX__检测到可能由AirJack发出的数据包"}

};

 

struct AlertDescriptionStr

{

     unsigned int ID;

     char* Name;

      char* Desp;

};

 

const AlertDescriptionStr Str[] =

{

     {0,"AAA","BBBB"},

     {1,"CCC","检测到可能由AirJack发出的数据包"}

};

 

void leak_memory(void)

{

      vector<unsigned int *> vec;

      for( int j = 0; j < 2; j++)

     {

           vec.push_back(new unsigned int(0));

     }

}

 

class NewClass

{

      void * p ;

public:

 NewClass()

{

      p = (void*) new char[10];

}

~NewClass()

{

      delete [] p;

}

};

 

int * p = new int(9);

 

int real_main_fun (int argc, char ** argv)

{

      leak_memory();

      return 0;

}

 

int main (int argc, char ** argv)

{

 

      string str("__YYY__检测到可能由AirJack发出的数据包");

      NewClass cls;

 

      int i = real_main_fun(argc, argv); // 原有的main函数体

 

      if(_CrtDumpMemoryLeaks())

      cout<< " memory leak " << endl;

      return i;

}

 

    第二种方法正好是它的补充,Memmory Validator可以检查程序整个运行过程中的内存分配情况,也可以将内存泄漏的位置显示出来,如图所示。

memory validato的界面

在实际应用第一种方法时,可以采用两个头文件,用于大型工程的调试,几乎不对其他部分代码产生影响。

 

-----------------------------------------------------------------------------

//config.h

#define MEMORY_DEBUG

#ifdef MEMORY_DEBUG

#include <stdlib.h>

#include <crtdbg.h>

#endif // MEMORY_DEBUG

------------------------------------------------------------------------------

//debug.h

#ifdef MEMORY_DEBUG

#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)

#define new DEBUG_NEW

#endif // MEMORY_DEBUG

-------------------------------------------------------------------------------

//main.cpp

#include "config.h” // config.h, 第一个头文件

#include "alertparser.h"

#include "alertinfocache.h"

#include <iostream>

#include <pcap.h>

#include "debug.h" //debug.h, 最后一个头文件

 

 int main (int argc, char ** argv)

{

 

      int i = real_main_fun(argc, argv); // 原有的main函数体

 

      if(_CrtDumpMemoryLeaks())

      cout<< " memory leak " << endl;

      return i;

}

目录
相关文章
|
24天前
|
XML C# 数据格式
掌握了在Windows平台上查看DLL依赖的方法
掌握了在Windows平台上查看DLL依赖的方法
166 4
|
7天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
25 4
|
27天前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
28天前
|
人工智能 JavaScript 网络安全
ToB项目身份认证AD集成(三完):利用ldap.js实现与windows AD对接实现用户搜索、认证、密码修改等功能 - 以及针对中文转义问题的补丁方法
本文详细介绍了如何使用 `ldapjs` 库在 Node.js 中实现与 Windows AD 的交互,包括用户搜索、身份验证、密码修改和重置等功能。通过创建 `LdapService` 类,提供了与 AD 服务器通信的完整解决方案,同时解决了中文字段在 LDAP 操作中被转义的问题。
|
30天前
|
存储 C语言 C++
【C++打怪之路Lv6】-- 内存管理
【C++打怪之路Lv6】-- 内存管理
37 0
【C++打怪之路Lv6】-- 内存管理
|
1月前
|
弹性计算 数据安全/隐私保护 Windows
阿里云国际版无法远程连接Windows服务器的排查方法
阿里云国际版无法远程连接Windows服务器的排查方法
|
1月前
|
C++
C/C++内存管理(下)
C/C++内存管理(下)
46 0
|
3月前
|
存储 编译器 C语言
【C语言篇】数据在内存中的存储(超详细)
浮点数就采⽤下⾯的规则表⽰,即指数E的真实值加上127(或1023),再将有效数字M去掉整数部分的1。
366 0
|
21天前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
44 1
|
26天前
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。