詳解windows下C/C++的內(nèi)存泄露檢測(cè)
檢測(cè)內(nèi)存泄露
利用Visual Studio調(diào)試器和CRT庫(kù)提供的檢測(cè)(malloc和new均適用)
程序只從單一位置退出時(shí):
1.需要以下頭文件:
#define _CRTDBG_MAP_ALLOC #include<stdlib.h> #include<crtdbg.h>
通過(guò)包含crtdbg.h,將malloc和free分別映射到_malloc_dbg和_free_dbg,用于內(nèi)存分配和釋放的跟蹤。
#define _CRTDBG_MAP_ALLOC語(yǔ)句用于提供額外的信息,非絕對(duì)必要。
2.在程序退出位置前使用以下語(yǔ)句:
_CrtDumpMemoryLeaks();
該語(yǔ)句會(huì)在輸出窗口顯示內(nèi)存泄露信息。
測(cè)試代碼
#define _CRTDBG_MAP_ALLOC
#include<stdio.h>
#include<stdlib.h>
#include<crtdbg.h>
#define NUM 10
int main()
{
char *test;
test = (char*)malloc(NUM * sizeof(char));
_CrtDumpMemoryLeaks();
return 0;
}
輸出結(jié)果
使用_CRTDBG_MAP_ALLOC時(shí):

未使用_CRTDBG_MAP_ALLOC時(shí):

如果將程序中的:
char *test; test = (char*)malloc(NUM * sizeof(char));
替換為:
char* name = new char[10];
也會(huì)得到同樣的結(jié)果(內(nèi)存位置由于自動(dòng)分配有所不同):

程序從多個(gè)位置退出時(shí):
1.同樣包含上述頭文件
2.在每個(gè)會(huì)退出程序的函數(shù)(包括main函數(shù))開(kāi)始處包含以下代碼:
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
程序會(huì)在退出時(shí)自動(dòng)調(diào)用_CrtDumpMemoryLeaks();。
測(cè)試代碼
#define _CRTDBG_MAP_ALLOC
#include<stdio.h>
#include<stdlib.h>
#include<crtdbg.h>
#define NUM 10
void test1();
void test2();
int main()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
char *test;
test = (char*)malloc(NUM * sizeof(char));
int a;
puts("input a number");
scanf_s("%d", &a, sizeof(int));
if (a > 10)
test1();
else if(a<20)
test2();
else
puts("exit point 3");
return 0;
}
void test1()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
puts("exit point 1");
exit(EXIT_SUCCESS);
}
void test2()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
puts("exit point 2");
exit(EXIT_SUCCESS);
}
輸出結(jié)果

定位內(nèi)存泄露
當(dāng)程序不大時(shí),內(nèi)存泄露位置可以輕易通過(guò)肉眼分辨或者代碼審計(jì)發(fā)現(xiàn)。但是當(dāng)程序較大的時(shí)候,就難以發(fā)現(xiàn)具體發(fā)生內(nèi)存泄露的位置。此時(shí)可以通過(guò)CRT庫(kù)的_CrtMenState結(jié)構(gòu)儲(chǔ)存內(nèi)存狀態(tài)。
使用該結(jié)構(gòu)類型需要定義變量用于儲(chǔ)存內(nèi)存狀態(tài):
_CrtMenState s1,s2,s3;
檢測(cè)指定位置內(nèi)存需要用到_CrtMenCheckPoint結(jié)構(gòu):
_CrtMenCheckPoint(&s1);
該語(yǔ)句將當(dāng)前位置的內(nèi)存狀態(tài)傳遞到_CrtMenState結(jié)構(gòu)變量s1中。
檢測(cè)兩個(gè)位置之間的內(nèi)存狀態(tài)需要用到_CrtMenDifference()函數(shù),同時(shí)需要一個(gè)新的_CrtMenState結(jié)構(gòu)變量用于存儲(chǔ)狀態(tài)之間的差異:
_CrtMemCheckpoint( &s1 ); _CrtMemCheckpoint( &s2 ); _CrtMemDifference( &s3, &s1, &s2);
轉(zhuǎn)儲(chǔ)_CrtMenState結(jié)構(gòu)的內(nèi)容需要用到_CrtMemDumpStatistics函數(shù):
_CrtMenDumpStatics(&s3);
測(cè)試代碼
#define _CRTDBG_MAP_ALLOC
#include<stdio.h>
#include<stdlib.h>
#include<crtdbg.h>
#define NUM 10
_CrtMemState s1, s2, s3;
void MEM(char *str, int n);
int main()
{
_CrtMemCheckpoint(&s1);
char *test=NULL;
MEM(test, NUM);
_CrtMemCheckpoint(&s2);
puts("test\n");
_CrtMemDifference(&s3, &s1, &s2);
_CrtMemDumpStatistics(&s3);
return 0;
}
void MEM(char *str, int n)
{
str = (char*)malloc(n * sizeof(char));
}
輸出結(jié)果
當(dāng)s1和s2之間調(diào)用了函數(shù)MEN()時(shí):

當(dāng)刪去程序中的
MEN(test, NUM);
即s1和s2之間沒(méi)有調(diào)用MEN()函數(shù)時(shí):

如果單純使用_CrtDumpMemoryLeaks();,只能顯示內(nèi)存分配的位置,即函數(shù)MEN()中分配內(nèi)存語(yǔ)句的位置,而不能定位到是哪一次對(duì)函數(shù)MEN()調(diào)用導(dǎo)致的內(nèi)存泄露,而通過(guò)結(jié)構(gòu)_CrtMenState,可以得到語(yǔ)句之間是否存在內(nèi)存分配,從而定位出內(nèi)存泄露的位置。
總結(jié)
內(nèi)存泄露的原因很簡(jiǎn)單,無(wú)非就是分配了內(nèi)存而沒(méi)有釋放,為了解決這個(gè)問(wèn)題,除了養(yǎng)成良好的習(xí)慣,還有要善用工具在編寫程序的時(shí)候?qū)崟r(shí)監(jiān)測(cè)是否出現(xiàn)內(nèi)存泄露,減少后期排bug時(shí)的工作量。
以上就是詳解windows下C/C++的內(nèi)存泄露檢測(cè)的詳細(xì)內(nèi)容,更多關(guān)于windows下C/C++的內(nèi)存泄露檢測(cè)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)電話簿項(xiàng)目
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)電話簿項(xiàng)目,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12
C語(yǔ)言 設(shè)計(jì)模式之訪問(wèn)者模式
這篇文章主要介紹了C語(yǔ)言 設(shè)計(jì)模式之訪問(wèn)者模式的相關(guān)資料,需要的朋友可以參考下2017-01-01
c語(yǔ)言實(shí)現(xiàn)數(shù)組循環(huán)左移m位
這篇文章主要介紹了c語(yǔ)言實(shí)現(xiàn)數(shù)組循環(huán)左移m位,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
基于Qt播放器的實(shí)現(xiàn)詳解(支持Rgb,YUV格式)
這篇文章主要為大家詳細(xì)介紹了如何利用Qt實(shí)現(xiàn)簡(jiǎn)易的播放器,可以支持支持Rgb,YUV格式。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以嘗試一下2022-12-12

