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;

}

目录
相关文章
|
9月前
|
监控 编译器 Windows
Qt5实现Windows平台串口通信
Qt5实现Windows平台串口通信
|
9月前
|
安全 Linux iOS开发
Binary Ninja 5.1.8104 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
Binary Ninja 5.1.8104 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
780 53
Binary Ninja 5.1.8104 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
|
11月前
|
Windows
Windows无法连接到打印机,请检查打印机名并重试 - 配置Windows 共享打印机出错;
WIN7共享打印机无法被WIN11连接,出现错误代码0x0000011b或0x00000709,可能是系统版本不兼容所致。本文提供多个轻量级修复工具,无需安装,双击即用,专为解决此类小问题设计,操作简单,适合普通用户快速修复打印机连接异常。
1359 0
|
9月前
|
Linux API iOS开发
Binary Ninja 4.2.6455 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
Binary Ninja 4.2.6455 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
692 14
Binary Ninja 4.2.6455 (macOS, Linux, Windows) - 反编译器、反汇编器、调试器和二进制分析平台
|
9月前
|
弹性计算 定位技术 数据中心
阿里云服务器配置选择方法:付费类型、地域及CPU内存配置全解析
阿里云服务器怎么选?2025最新指南:就近选择地域,降低延迟;长期使用选包年包月,短期灵活选按量付费;企业选2核4G5M仅199元/年,个人选2核2G3M低至99元/年,高性价比爆款推荐,轻松上云。
1078 11
|
9月前
|
Ubuntu API C++
C++标准库、Windows API及Ubuntu API的综合应用
总之,C++标准库、Windows API和Ubuntu API的综合应用是一项挑战性较大的任务,需要开发者具备跨平台编程的深入知识和丰富经验。通过合理的架构设计和有效的工具选择,可以在不同的操作系统平台上高效地开发和部署应用程序。
329 11
|
10月前
|
安全 Linux API
JEB Pro v5.31 (macOS, Linux, Windows) - 逆向工程平台
JEB Pro v5.31 (macOS, Linux, Windows) - 逆向工程平台
308 0
|
11月前
|
Unix Linux 编译器
解决在Windows平台上运行Golang程序时出现的syscall.SIGUSR1未定义错误。
通过这种结构,你的代码既可以在支持 SIGUSR1 信号的系统上正常工作,又可以在不支持这些信号的 Windows 系统上编译通过,确保跨平台的兼容性和功能的完整性。
388 0
|
Unix Linux iOS开发
Splunk Enterprise 10.0.0 (macOS, Linux, Windows) - 搜索、分析和可视化,数据全面洞察平台
Splunk Enterprise 10.0.0 (macOS, Linux, Windows) - 搜索、分析和可视化,数据全面洞察平台
310 0
|
存储 Windows
内存卡坏了还能修吗?4种常见修复方法
内存卡出现“无法保存”或“存储异常”等问题时,不一定是硬件损坏,可能是系统错误或文件系统异常导致。本文介绍几种亲测有效的修复方法:1) 更换读卡设备排除接触问题;2) 格式化修复文件系统(需先备份数据);3) 使用DiskGenius检测坏道;4) 借助厂商工具深度修复。同时提供日常保养建议,如避免高温环境、养成数据备份习惯,延长内存卡使用寿命。通过这些方法,多数问题可轻松解决,无需更换硬件。