国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

用V C++檢測(cè)和隔離內(nèi)存泄漏

2019-11-17 05:48:53
字體:
供稿:網(wǎng)友
       

  具有動(dòng)態(tài)的分配和釋放內(nèi)存的能力是C/C++程序語言的重要特色之一。Visual C++ debugger 和 CRT庫提供了一系列有效的檢測(cè)和鑒定內(nèi)存泄漏的工具。

  設(shè)置內(nèi)存泄漏檢測(cè)

  檢測(cè)內(nèi)存泄漏的基本工具是調(diào)試器和CRT調(diào)試堆函數(shù)。為了使用調(diào)試堆函數(shù),在你的程序中你必須含有下面的說明: 
  #define _CRTDBG_MAP_ALLOC#include #include 

  #include說明必須按順序說明。假如改變了順序,所用的函數(shù)可能不能正常工作。包含crtdbg.h的_malloc_dbg和 _free_dbg將 malloc和free函數(shù)映射到測(cè)試版中,它可以跟蹤內(nèi)存的分配和釋放。這種映射僅僅在一個(gè)測(cè)試體系中發(fā)生(也就是說,僅僅當(dāng)_DEBUG被定義的時(shí)候)。釋放的體系使用通常的malloc和 free功能。

  #define說明映射CRT堆函數(shù)的低級(jí)版本到相應(yīng)的測(cè)試版本。這個(gè)說明是不需要的,但是沒有它,內(nèi)存泄漏處含有的只是沒有多大用處的信息。

  一旦你已經(jīng)增加了剛才的說明,你能夠通過在你的程序中包含下面的說明來釋放內(nèi)存信息: 
  _CrtDumpMemoryLeaks();

  當(dāng)調(diào)試情況下運(yùn)行程序時(shí),在輸出窗口的Debug 標(biāo)簽處_CrtDumpMemoryLeaks表現(xiàn)出內(nèi)存泄漏的信息。內(nèi)存泄漏信息類似下面這樣: 
Detected memory leaks!
Dumping objects ->
C:PROGRAM FILESVISUAL STUDIOMyProjectsleaktestleaktest.cpp(20) :  normal block at 
0x00780E80, 64 bytes long.
Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
Object dump complete. 

  假如你沒有用#define _CRTDBG_MAP_ALLOC說明,內(nèi)存漏洞堆存處類似下面這樣:
Detected memory leaks!
Dumping objects ->
 normal block at 0x00780E80, 64 bytes long.
Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
Object dump complete.

  當(dāng)_CRTDBG_MAP_ALLOC被定義時(shí),_CrtDumpMemoryLeaks給了你更多的有用信息。假如_CRTDBG_MAP_ALLOC沒有被定義,那么將向你如下顯示:

  內(nèi)存分配數(shù)值(花括號(hào)內(nèi))
  模塊的類型(normal、client或者CRT)
  以十六進(jìn)制格式定位的內(nèi)存
  以字節(jié)計(jì)模塊的大小
  第一個(gè)十六字節(jié)的內(nèi)容(也可以用十六進(jìn)制)
  當(dāng)定義了_CRTDBG_MAP_ALLOC的時(shí)候,顯示的內(nèi)容也向你展現(xiàn)了出現(xiàn)泄漏內(nèi)存所分配地方的文件。在文件名之后括號(hào)內(nèi)的數(shù)字(20,以此為例)是文件內(nèi)的行數(shù)值。假如你雙擊包含行數(shù)值和文件名的輸出行, 
  C:PROGRAM FILESVISUAL STUDIOMyProjectsleaktestleaktest.cpp(20) :  normal block at 
0x00780E80, 64 bytes long.

  指針將會(huì)跳到源文件中內(nèi)存被分配地方的行(在上面的情況下,leaktest.cpp的行號(hào)為20)。選擇輸出行并按F4將有同樣的效果。 
 
  使用_CrtSetDbgFlag
  假如你的程序總是在同一各地方存在,那么調(diào)用_CrtDumpMemoryLeaks時(shí)非常輕易的。但是,假如你的程序需要在多個(gè)位置退出該怎么辦?在每一個(gè)可能的出口處假如不調(diào)用_CrtDumpMemoryLeaks,你可在你的程序開始處包含下面的調(diào)用:
  _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF  _CRTDBG_LEAK_CHECK_DF);
  當(dāng)程序退出時(shí),這個(gè)說明自動(dòng)地調(diào)用_CrtDumpMemoryLeaks。你必須設(shè)置兩個(gè)位域,_CRTDBG_ALLOC_MEM_DF和 _CRTDBG_LEAK_CHECK_DF。

  翻譯內(nèi)存模塊的類型
  內(nèi)存泄漏信息鑒別泄漏內(nèi)存的每一個(gè)模塊作為一個(gè)普通的模塊、一個(gè)客戶模塊或者一個(gè)CRT模塊。實(shí)際上,普通的模塊和客戶模塊是你可能留心的唯一類型。
  一個(gè)普通模塊(normal block)是由你的程序分配的普通內(nèi)存。
  一個(gè)客戶模塊(client block)是一種非凡的內(nèi)存模塊,它由于需要一個(gè)析構(gòu)函數(shù)的對(duì)象而被Microsoft Foundation Classes (MFC)所使用。MFC new操作子建立一個(gè)普通模塊或者一個(gè)客戶模塊,來適合被創(chuàng)建的模塊。

  一個(gè)CTR模塊是由CRT庫提供自己使用而分配的內(nèi)存模塊。CRT庫對(duì)這些模塊來治理自己的去分配,因此你不可能在內(nèi)存泄漏報(bào)告中注重到這些,除非有些地方有嚴(yán)重的錯(cuò)誤(例如,CRT庫崩潰)。
  在內(nèi)存泄漏信息中有兩種你從來沒有見過的模塊類型:
  空閑模塊(free block)是一種被釋放的內(nèi)存模塊
  Ignore block是你已經(jīng)非凡標(biāo)記過以至于在內(nèi)存泄漏報(bào)告中不會(huì)出現(xiàn)的模塊。

  設(shè)置CRT報(bào)告樣式
  像以前的一樣,按默認(rèn)方式,_CrtDumpMemoryLeaks傾卸內(nèi)存泄漏信息到輸出窗口的Debug窗格。你可以運(yùn)用_CrtSetReportMode重新設(shè)置它到堆存處,到另一個(gè)位置。假如你使用一個(gè)庫,它可能重新設(shè)置輸出到另一個(gè)位置。在這種情況下,你能夠利用下面的說明來設(shè)置輸出位置回到輸出窗口:
  _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );
  關(guān)于使用_CrtSetReportMode去發(fā)送輸出信息到另一個(gè)位置,要看Visual C++文件的_CrtSetReportMode節(jié)。

  在內(nèi)存分配數(shù)目處設(shè)置一個(gè)斷點(diǎn)
  在內(nèi)存泄漏報(bào)告中的文件名和行號(hào)可告訴你泄漏的內(nèi)存在那里被分配,但是了解內(nèi)存在那里分配對(duì)于鑒定問題不總是充分的。在一個(gè)程序運(yùn)行過程中,經(jīng)常是一個(gè)分配將會(huì)被調(diào)用很多次,但是它可能在某次調(diào)用中泄漏內(nèi)存。為了確定問題,你必須不但知道泄漏的內(nèi)存在那里分配,還要知道泄漏發(fā)生的條件。對(duì)你來說,使它成為可能的那條信息是內(nèi)存分配號(hào)。當(dāng)那些被顯示的時(shí)候,文件名和行號(hào)之后,這是在curly brace中出現(xiàn)的數(shù)值。例如,在下面的輸出中,"18"是內(nèi)存分配號(hào)。它的意思是泄漏的內(nèi)存是你程序中內(nèi)存分配的第十八個(gè)模塊。 
Detected memory leaks!
Dumping objects ->
C:PROGRAM FILESVISUAL STUDIOMyProjectsleaktestleaktest.cpp(20) :  normal block at 
0x00780E80, 64 bytes long.
Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
Object dump complete.

  CRT庫計(jì)算在程序運(yùn)行期間分配的所用內(nèi)存模塊,包括CRT自己分配的內(nèi)存或者諸如MFC的其它模塊。因此帶有分配號(hào)n的一個(gè)對(duì)象是在你的程序中分配的第n個(gè)對(duì)象,但不可能是由代碼分配的第n個(gè)對(duì)象。(在大部分情況下,它是不會(huì)的。)

  你可以利用分配號(hào)在內(nèi)存分配的地方設(shè)置一個(gè)斷點(diǎn)。為了做這些,你可以距離你的程序開始很近處,設(shè)置一個(gè)位置斷點(diǎn)。當(dāng)你的程序在那一點(diǎn)暫停時(shí),你能夠從QuickWatch對(duì)話框或者Watch窗口設(shè)置這樣一個(gè)位置斷點(diǎn)。例如,在Watch窗口中,在Name欄鍵入下面的表達(dá)式: 
_crtBreakAlloc

  假如你正在用CRT庫的多線程的dynamic-link library (DLL)版本,你必須含有上下文操作符,像這里說明的: 
_crtBreakAlloc

  現(xiàn)在,按RETURN。調(diào)試器評(píng)估調(diào)用并且把結(jié)果放置在Value欄。假如你在內(nèi)存分配過程中還沒有設(shè)置任何斷點(diǎn),那么這個(gè)值是-1。使用你想中斷處內(nèi)存分配的分配數(shù)值來代替Value表中的值--例如,18 去中斷早期在輸出過程中展現(xiàn)的分配。

  當(dāng)你在你感愛好的內(nèi)存分配處設(shè)置斷點(diǎn)之后,你能夠繼續(xù)調(diào)試。在與從前相同的條件下,運(yùn)行程序時(shí)一定要小心,因而分配的順序不會(huì)改變。當(dāng)你的程序在一個(gè)非凡的內(nèi)存分配點(diǎn)中斷的時(shí)候,你能夠查看Call Stack窗口和其他的測(cè)試信息來確定在此條件下內(nèi)存的分配。假如需要的話,你可以繼續(xù)從那一點(diǎn)執(zhí)行程序,以至于了解對(duì)象到底發(fā)生了什么事,同時(shí)還可能確定為了沒有正確地被去分配。(對(duì)對(duì)象設(shè)置一個(gè)數(shù)據(jù)斷點(diǎn)是很有幫助的。)

  雖然在調(diào)試器中設(shè)置內(nèi)存分配斷點(diǎn)通常更加輕易,但是假如你喜歡的話,你可以在你的代碼中設(shè)置它們。為了在你的代碼中設(shè)置一個(gè)內(nèi)存分配斷點(diǎn),可以增加這樣一行(對(duì)于第十八個(gè)內(nèi)存分配): 
_crtBreakAlloc = 18;

  最為一個(gè)選擇,你可以使用有相同效果的_CrtSetBreakAlloc函數(shù)。 
_CrtSetBreakAlloc(18);

  比較內(nèi)存狀態(tài)

  定位內(nèi)存泄漏的另一個(gè)方法就是在要害點(diǎn)對(duì)應(yīng)用程序的內(nèi)存狀態(tài)做快照。CRT庫提供了一個(gè)結(jié)構(gòu)類型,_CrtMemState。你可以使用它來存儲(chǔ)內(nèi)存狀態(tài)的一個(gè)快照。 
_CrtMemState s1, s2, s3;

  為了在特定點(diǎn)對(duì)內(nèi)存狀態(tài)進(jìn)行快照,可以傳遞一個(gè)_CrtMemState結(jié)構(gòu)到he _CrtMemCheckpoint函數(shù)。此函數(shù)用當(dāng)時(shí)內(nèi)存狀態(tài)的一個(gè)快照來填充此結(jié)構(gòu): 
_CrtMemCheckpoint( &s1 );

  你可以通過傳遞此結(jié)構(gòu)到_CrtMemDumpStatistics函數(shù)來傾卸_CrtMemState結(jié)構(gòu)的任意點(diǎn)的內(nèi)容: 
_CrtMemDumpStatistics( &s3 );( &s1 );

  此函數(shù)打印出類似于下面這樣的一堆內(nèi)存分配信息: 
0 bytes in 0 Free Blocks.
0 bytes in 0 Normal Blocks.
3071 bytes in 16 CRT Blocks.

0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 3071 bytes.
Total allocations: 3764 bytes.

  為了確定一個(gè)內(nèi)存泄漏是否在一節(jié)代碼中出現(xiàn),你可以在此節(jié)前和此節(jié)后對(duì)內(nèi)存狀態(tài)作快照,然后用_CrtMemDifference比較兩種狀態(tài): 
_CrtMemCheckpoint( &s1 );
// memory allocations take place here
_CrtMemCheckpoint( &s2 );

if ( _CrtMemDifference( &s3, &s1, &s2) ) 
   _CrtMemDumpStatistics( &s3 );

  像名字暗示的一樣,_CrtMemDifference比較兩個(gè)內(nèi)存狀態(tài)(最先的兩個(gè)參數(shù))并且產(chǎn)生一個(gè)不同于這兩個(gè)狀態(tài)的結(jié)果(第三個(gè)參數(shù))。在你的程序開始和結(jié)尾處的_CrtMemCheckpoint調(diào)用和使有_CrtMemDifference來比較結(jié)果為檢測(cè)內(nèi)存泄漏提供了另一種方法。假如一個(gè)泄漏被檢測(cè)到,那么可以使用_CrtMemCheckpoint調(diào)用來分割你的程序并且使用二元binary search technique來定位泄漏。 

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 大庆市| 永泰县| 盐源县| 富锦市| 博白县| 青阳县| 益阳市| 临沭县| 兴海县| 宝应县| 阿拉善左旗| 渑池县| 和政县| 上林县| 湖州市| 饶阳县| 连州市| 鄂托克前旗| 清徐县| 资源县| 江安县| 南和县| 闽清县| 丹东市| 应城市| 建水县| 吐鲁番市| 宿州市| 海宁市| 武穴市| 阜阳市| 武强县| 十堰市| 岗巴县| 海丰县| 同德县| 黄龙县| 沙河市| 广昌县| 文昌市| 邹平县|