VS内存泄漏检查 2020/3/15
1.1.说明:
VS调试器和C运行时(CRT)库为我们提供了检测和识别内存泄漏的有效方法
1.2.原理:
内存分配要通过CRT在运行时实现,只要在分配内存和释放内存时分别做好记录,
程序结束时对比分配内存和释放内存的记录就可以确定是不是有内存泄漏。
1.3.vs中启用内存检测:
步骤1:程序开头包含: (注意顺序)
#define _CRTDBG_MAP_ALLOC//将CRT堆函数的基版本映射到对应的“Debug”版本
#include <stdlib.h>
#include <crtdbg.h> //将malloc,free等映射到调试版本(跟踪内存分配和释放)
步骤2:程序尾部包括_CrtDumpMemoryLeaks();//来转储内存泄漏信息
步骤3:运行程序(实例1):结果显示
Dumping objects ->
{154} normal block at 0x00F26078, 100 bytes long.
步骤4:在程序运行第一句添加:_CrtSetBreakAlloc(154);//产生中断(154要根据实际填写)
a)运行程序(实例2)中断
b)在VS下的--自动窗口--调用堆栈:查看输出
> test.exe!GetMemory(char * p, int num) 行 37 C++
说明源程序的37有问题
注意:
并不是说有normal block一定就有内存泄漏,当有全局变量时,全局变量释放示在main函数退出后,
所以在main函数最后_CrtDumpMemoryLeaks()会认为全局申请内存没释放,造成内存泄漏假象。
规避:
通常把全局变量声明成指针;int *pInt=new int;...;delete pInt;然后再调用_CrtDumpMemoryLeaks()
2.实例:
实例1:
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <iostream>
using namespace std;
_CrtMemState s1, s2, s3;//CRT 库结构类型,可用它存储内存状态的快照
void GetMemory(char *p, int num)
{
p = (char*)malloc(sizeof(char) * num);
}
int main(int argc, char** argv)
{
// _CrtSetBreakAlloc(154);
_CrtMemCheckpoint(&s1);//用当前内存状态的快照填充此结构
char *str = NULL;
GetMemory(str, 100);
_CrtMemCheckpoint(&s2);
if (_CrtMemDifference(&s3, &s1, &s2))//比较两内存状态(s1和s2)生成这两个状态之间差异的结果(s3)
_CrtMemDumpStatistics(&s3);//向_CrtMemDumpStatistics传递_CrtMemState结构,可在任意点转储该结构内容
cout << "Memory leak test!" << endl;
_CrtDumpMemoryLeaks();//检查、定位内存泄漏此方法必须在debug模式下进行
return 0;
}
//当在调试器下运行程序时,_CrtDumpMemoryLeaks 将在“输出”窗口中显示内存泄漏信息。
//内存泄漏信息如下所示:
/*
0 bytes in 0 Free Blocks.
100 bytes in 1 Normal Blocks.
0 bytes in 0 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used : 0 bytes.
Total allocations : 100 bytes.
Detected memory leaks!
Dumping objects ->
{154} normal block at 0x00F26078, 100 bytes long.
Data : < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
*/
说明:
//{ 154 } normal block at 0x00F26078, 100 bytes long.
//被{}包围154就是内存泄漏定位值,100 bytes long就是说这个地方有100比特内存没有释放。
实例2:
...//同上
int main(int argc, char** argv)
{
_CrtSetBreakAlloc(154);//首行
...//同上
}
实例3:
#include<crtdbg.h>
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
int main()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
_CrtSetBreakAlloc(147);//
int *temp = new int(100);
_CrtDumpMemoryLeaks();//或将此放到程序的最后
}
/*
Detected memory leaks!
Dumping objects ->
c:\users\administrator\source\repos\test\test\test.cpp(28) : {77} normal block at 0x012F6248, 4 bytes long.
Data : < d > 64 00 00 00
Object dump complete.
Detected memory leaks!
Dumping objects ->
c : \users\administrator\source\repos\test\test\test.cpp(28) : {77} normal block at 0x012F6248, 4 bytes long.
Data : < d > 64 00 00 00
*/