關於VC6.0下記憶體泄露的監測

來源:互聯網
上載者:User


今天著手解決一個現有程式的記憶體泄露問題,以前從沒用過相關檢測的工具、手段!

 

搜了幾篇文章,感覺還不錯:

 

主要的偵查工具是debuger和crt堆除錯函數:

 

http://bbs.17testing.com/viewthread.php?tid=8516  掃盲——記憶體流失的有關知識

 

http://leoman95.spaces.live.com/blog/cns!87f442ce8fa434b1!131.entry VC++6.0中記憶體流失檢測

 

http://www.360doc.com/content/081028/22/7635_1840985.html vc記憶體泄露檢測-常用技巧(轉載)

 

http://fafeng.blogbus.com/logs/7525571.html 記憶體泄露偵查工具

 

http://www.cppblog.com/bigsml/archive/2006/10/19/13860.html  用BoundChecker檢測記憶體泄露(zz)

 

http://blueluhan.spaces.live.com/blog/cns!B0E40D35BB595164!1412.entry 使用BoundChecker的好處

 

【推薦】http://blog.csdn.net/seawen/archive/2009/01/05/3714128.aspx VC記憶體流失偵查工具_Visual Leak Detector

 

推薦第三方內錯泄露偵查工具

Purify   很好,很強大,收費

BoundsChecker 很好,很強大,收費

Visual Leak Detector 很好,很淺大,免費,源碼都有,強烈推薦

 

這裡主要介紹一下用法:

 

需在檔案中包含以下

標頭檔和宏定義:

#include<stdlib.h> 

#include<crtdbg.h> 

#define _CRTDBG_MAP_ALLOC 

 

 

環境:

 

列印的記憶體訊息只在調試狀態下,output視窗的debug頁輸出。

 

函數:

 

_CrtDumpMemoryLeaks(); 報告當前程式記憶體泄露狀況

 

因為程式可能在多個出口,在main函數入口加上這句:

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

即可保證,在程式結束時一定調用一次_CrtDumpMemoryLeaks();

 

_CrtMemState s1; 聲明一個記憶體快照的結構體資訊

 

_CrtMemCheckpoint( &s1 ); 將當前記憶體快照儲存到s1中

 

_CrtMemDumpStatistics(&s1); 列印s1記憶體快照資訊

 

_CrtMemDifference(&s3, &s1, &s2);將快照s1和s2的差異,儲存到s3中

 

_crtBreakAlloc(45); 此函數用來在記憶體第45次分配時,產生中斷,也可以在Watch視窗中,

name欄寫“_crtBreakAlloc”, value值寫“45”,同樣會產生中斷!便於調試!

 

 

注意:

在vc6.0下,若你的程式包含<iostream.h><string>等標頭檔,你會發現總是會報告記憶體泄露:

 

 

Detected memory leaks!

Dumping objects ->

{45} normal block at 0x00372638, 33 bytes long.

 Data: < C              > 00 43 00 CD CD CD CD CD CD CD CD CD CD CD CD CD 

{44} normal block at 0x003725D0, 40 bytes long.

 Data: < |L             > 14 7C 4C 10 16 00 00 00 00 00 00 00 00 00 00 00 

Object dump complete.

 

 

這估計是vc6的bug吧!

 

附上一個測試代碼:

//////////////////////////////////////////////////////////////////////////<br />//功能:vc6.0 Debugger + CRT示範程式<br />//說明:使用該程式,需要在project中設定屬性,將MFC作為共用的DLL<br />//作者:wuming<br />//////////////////////////////////////////////////////////////////////////<br />#include "stdio.h"<br />#include<stdlib.h><br />#include<crtdbg.h><br />#include <afx.h><br />#define _CRTDBG_MAP_ALLOC<br />//定位記憶體泄露來源程式行<br />#ifdef _DEBUG<br />#define new DEBUG_NEW<br />#endif<br />int main()<br />{<br />//設定開關,在程式結束時,自動報告一次記憶體泄露情況<br />_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );<br />//重新導向報告<br />freopen( "out.txt", "w", stderr);<br />_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );<br />_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR );<br />_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );<br />_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR );<br />_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );<br />_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR );<br />_CrtMemState s1, s2, s3;<br />//trace本身也會造成mem leak在vc6.0下<br />TRACE("/n................ Start Main() ................../n");<br />_CrtMemCheckpoint( &s1 );<br />_CrtMemDumpStatistics(&s1);<br />new char[100];<br />TRACE("/n................. Report Mem Leak() ............/n");<br />_CrtDumpMemoryLeaks();</p><p>TRACE("/n................ First ff() ................../n");<br />_CrtMemCheckpoint(&s2);<br />_CrtMemDumpStatistics(&s2);<br />TRACE("/n................ Difference() ................../n");<br />_CrtMemDifference(&s3, &s1, &s2);<br />_CrtMemDumpStatistics(&s3);<br />TRACE("/n.................. The Last Auto Report Mem Leak() ............/n");<br /> return 0;<br />}  

 

 

第三方工具VLD用法:visual leak detector

 

現在vld已經有了1.9的beta版,我用的是1.0版本,

1. 下載

    解壓後,會有:

    三個lib檔案,“vld.lib”,“vldmt.lib”,“vldmtdll.lib”

    兩個.h檔案,“vld.h”,“vldapi.h”

    一個dll檔案,“dbhelp.dll”

2. 安裝

       把lib檔案拷貝到vc6.0安裝目錄“.../Microsoft Visual Studio/VC98/Lib”下,

       然後把.h檔案拷貝到自己的工程目錄下,

3. 使用

       你工程的源碼裡,在程式入口檔案處,第一個include那兩個.h檔案,若檔案有“stdafx.h”,則

       在include "stdafx.h"後,再包含兩個檔案。

4. 報告輸出

       vld是在調式狀態下,才會進行記憶體檢測,最終的報告也輸出在output視窗的debug頁。

       對於非調試執行程式,vld不作任何檢查,這樣,及時發布程式,也無需注釋掉vld,不影響效能!

5. 注意

       若是發現報告內容都是地址碼,沒有函數名路徑資訊,則拷貝dbhelp.dll到工程的debug目錄下即可!

 

 

 

附錄:記憶體流失的發生方式(摘自: http://fafeng.blogbus.com/logs/7525571.html)

1.常發性記憶體流失。發生記憶體流失的代碼會被多次執行到,每次被執行的時候都會導致一塊記憶體流失。
2.偶發性記憶體流失。發生記憶體流失的代碼只有在某些特定環境或操作過程下才會發生。常發性和偶發性是相對的。對於特定的環境,偶發性的也許就變成了常發性的。所以測試環境和測試方法對檢測記憶體流失至關重要。
3.一次性記憶體流失。發生記憶體流失的代碼只會被執行一次,或者由於演算法上的缺陷,導致總會有一塊且僅有一塊記憶體發生泄漏。
4.隱式記憶體流失。程式在運行過程中不停的分配記憶體,但是直到結束的時候才釋放記憶體。嚴格的說這裡並沒有發生記憶體流失,因為最終程式釋放了所有申請的記憶體。但是對於一個伺服器程式,需要運行幾天,幾周甚至幾個月,不及時釋放記憶體也可能導致最終耗盡系統的所有記憶體。所以,我們稱這類記憶體流失為隱式記憶體流失。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.