C++使用CRT庫檢測(cè)內(nèi)存泄漏的方法詳解
內(nèi)存泄漏是 C/C++ 應(yīng)用程序中最微妙、最難以發(fā)現(xiàn)的 bug,存泄漏是由于之前分配的內(nèi)存未能正確解除分配而導(dǎo)致的。 最開始的少量?jī)?nèi)存泄漏可能沒被發(fā)現(xiàn),但隨時(shí)間推移,會(huì)導(dǎo)致各種問題,從性能變差到程序由于內(nèi)存不足而崩潰。 內(nèi)存泄漏的應(yīng)用會(huì)耗盡全部可用內(nèi)存,導(dǎo)致其它程序崩潰,從而讓人難以分辨是哪個(gè)程序引發(fā)問題。 即使無害的內(nèi)存泄漏也可能表明存在其他應(yīng)糾正的問題。
一、CRT 庫簡(jiǎn)介
內(nèi)存泄漏的檢測(cè)工具有很多,大多數(shù)的內(nèi)存泄漏檢測(cè)工具都要我們手動(dòng)安裝才能使用,但是CRT(C 運(yùn)行時(shí)庫)庫,是Visual Studio
自帶的,所以我們可以開箱即用,無需安裝其他的內(nèi)存泄漏檢測(cè)工具。
所以下面我們就來一起學(xué)習(xí)一下如何使用CRT庫檢測(cè)內(nèi)存泄漏:
CRT檢測(cè)內(nèi)存泄漏原理:內(nèi)存分配要通過CRT在運(yùn)行時(shí)實(shí)現(xiàn),只要在分配內(nèi)存和釋放內(nèi)存時(shí)分別做好記錄,程序結(jié)束時(shí)對(duì)比分配內(nèi)存和釋放內(nèi)存的記錄就可以確定是不是有內(nèi)存泄漏。
二、CRT 庫的使用
1、啟用內(nèi)存泄漏檢測(cè)
檢測(cè)內(nèi)存泄漏的主要工具是 「C/C++ 調(diào)試程序」和 「CRT 調(diào)試堆函數(shù)」,若要啟用調(diào)試堆的所有函數(shù),在 C++ 程序中,按以下順序包含以下語句:
#define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h>
#define
語句將 CRT 堆函數(shù)的基礎(chǔ)版本映射到對(duì)應(yīng)的調(diào)試版本,如果省略#define
語句,內(nèi)存泄漏轉(zhuǎn)儲(chǔ)包含的有用信息將有所簡(jiǎn)化。#include <crtdbg.h>
會(huì)將malloc
和free
函數(shù)映射到其調(diào)試版本_malloc_dbg
和_free_dbg
,它們跟蹤內(nèi)存分配和解除分配。 此映射只在包含_DEBUG
的調(diào)試版本中發(fā)生。 發(fā)布版本則會(huì)使用普通的malloc
和free
函數(shù)。
2、設(shè)置應(yīng)用退出時(shí)顯示內(nèi)存泄漏報(bào)告
在使用了上面的語句啟用調(diào)試堆函數(shù)后,需要在應(yīng)用出口點(diǎn)之前放置 _CrtDumpMemoryLeaks
,從而在應(yīng)用退出時(shí)顯示內(nèi)存泄漏報(bào)告。
_CrtDumpMemoryLeaks();
如果你的應(yīng)用程序有多個(gè)出口點(diǎn),每一個(gè)出口點(diǎn)都要設(shè)置這個(gè)函數(shù)也太復(fù)雜了,所以我們可以在應(yīng)用程序開頭調(diào)用 _CrtSetDbgFlag
并傳入一些參數(shù)來幫助我們簡(jiǎn)化這個(gè)操作。
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
_CRTDBG_ALLOC_MEM_DF
- 含義:?jiǎn)⒂脙?nèi)存分配調(diào)試。
- 作用:當(dāng)啟用該標(biāo)志時(shí),CRT 會(huì)在每次內(nèi)存分配時(shí)記錄調(diào)試信息,包括分配的文件名和行號(hào)。這些信息在內(nèi)存泄漏報(bào)告中非常有用,可以幫助你確定內(nèi)存泄漏發(fā)生的位置。
_CRTDBG_LEAK_CHECK_DF
- 含義:?jiǎn)⒂脙?nèi)存泄漏檢測(cè)。
- 作用:當(dāng)啟用該標(biāo)志時(shí),程序退出時(shí) CRT 會(huì)自動(dòng)檢查未釋放的內(nèi)存,并生成內(nèi)存泄漏報(bào)告。這可以幫助你發(fā)現(xiàn)和修復(fù)內(nèi)存泄漏問題。
_CRTDBG_CHECK_ALWAYS_DF
- 作用:當(dāng)設(shè)置 該標(biāo)志時(shí),CRT會(huì)在每次分配或釋放內(nèi)存時(shí)檢查整個(gè)堆的完整性。這意味著每次內(nèi)存操作(如 malloc、free、new、delete)都會(huì)觸發(fā)堆完整性檢查。通過這種操作能檢測(cè)一些內(nèi)存越界的問題。當(dāng)然也可以手動(dòng)調(diào)用
_CrtCheckMemory()
函數(shù)進(jìn)行立即檢測(cè)。
- 作用:當(dāng)設(shè)置 該標(biāo)志時(shí),CRT會(huì)在每次分配或釋放內(nèi)存時(shí)檢查整個(gè)堆的完整性。這意味著每次內(nèi)存操作(如 malloc、free、new、delete)都會(huì)觸發(fā)堆完整性檢查。通過這種操作能檢測(cè)一些內(nèi)存越界的問題。當(dāng)然也可以手動(dòng)調(diào)用
3、豐富內(nèi)存泄漏報(bào)告
為了豐富我們的內(nèi)存泄漏報(bào)告,我們可以重定義 new malloc
用以捕獲文件名和行號(hào)
// 重定義 new malloc 以捕獲文件名和行號(hào) #ifdef _DEBUG #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) #define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__) #endif
4、演示使用
我們通過下面的一個(gè)完整的示例,展示如何使用 CRT進(jìn)行內(nèi)存泄漏檢測(cè):
#define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #include <iostream> // 重定義 new malloc 以捕獲文件名和行號(hào) #ifdef _DEBUG #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) #define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__) #endif void leakMemory() { int* p = new int[10]; // 這是一個(gè)內(nèi)存泄漏示例 } int main() { // 啟用內(nèi)存分配調(diào)試和內(nèi)存泄漏檢測(cè) _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_ALWAYS_DF); leakMemory(); std::cout << "Program finished." << std::endl; return 0; }
我們按F5
進(jìn)行調(diào)試時(shí),當(dāng)程序運(yùn)行完畢,我們?cè)谳敵龃翱诳梢钥吹剑?/p>
通過雙擊這條日志,我們能直接跳轉(zhuǎn)到內(nèi)存分配的位置。
這條日志包含的內(nèi)容解釋:
- 內(nèi)存分配編號(hào),在示例中為 164
- 塊類型,在示例中為 normal 。
- 十六進(jìn)制內(nèi)存位置,在示例中為0x0167D7C0。
- 塊的大小,在示例中為 40 bytes。
- 塊中前 16 個(gè)字節(jié)的數(shù)據(jù)(十六進(jìn)制形式)
到此這篇關(guān)于C++使用CRT庫檢測(cè)內(nèi)存泄漏的方法詳解的文章就介紹到這了,更多相關(guān)C++ CRT檢測(cè)內(nèi)存泄漏內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)自定義撤銷重做功能的示例代碼
在使用c++做界面開發(fā)的時(shí)候,尤其是實(shí)現(xiàn)白板功能時(shí)需要自己實(shí)現(xiàn)一套撤銷重做功能.如果是qt則有QUndoable對(duì)象,可以直接拿來用。但是如果是使用gdi繪圖,則可能需要自己實(shí)現(xiàn)了。本文就來用C++實(shí)現(xiàn)自定義撤銷重做功能,需要的可以參考一下2022-12-12C++ 中約瑟夫環(huán)替換計(jì)數(shù)器m(數(shù)組解決)
這篇文章主要介紹了C++ 中約瑟夫環(huán)替換計(jì)數(shù)器m(數(shù)組解決)的相關(guān)資料,需要的朋友可以參考下2017-05-05Qt中CQGUI框架之陰影圓角窗口實(shí)現(xiàn)
這篇文章主要介紹了Qt中CQGUI框架之陰影圓角窗口實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03C++實(shí)現(xiàn)動(dòng)態(tài)煙花代碼
這篇文章主要介紹了利用C++實(shí)現(xiàn)的放煙花程序,用到了EGE圖形庫,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C++有一定幫助,需要的可以參考一下2023-01-01C++如何實(shí)現(xiàn)BCD碼和ASCII碼的相互轉(zhuǎn)換
這篇文章主要介紹了C++實(shí)現(xiàn)BCD碼和ASCII碼互轉(zhuǎn),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06C語言全面梳理結(jié)構(gòu)體知識(shí)點(diǎn)
結(jié)構(gòu)體是一些值的集合,這些值稱為成員變量,結(jié)構(gòu)體的每個(gè)成員可以是不同類型的變量。本文將通過示例為大家詳細(xì)講講C語言中結(jié)構(gòu)體的使用,需要的可以參考一下2022-07-07