青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

盡管這個概念已經讓人說濫了 ,還是想簡單記錄一下, 以備以后查詢。

#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif


int _tmain(int argc, _TCHAR* argv[])
{
    char* p = new char();
    char* pp = new char[10];
    char* ppp = (char*)malloc(10);

    _CrtDumpMemoryLeaks();

    return 0;
}

主要原理是運用Crt 的內存調試功能, 通過宏替代默認的operator new, 讓它被下面版本替代:
void *__CRTDECL operator new(
        size_t cb,
        int nBlockUse,
        const char * szFileName,
        int nLine
        )
        _THROW1(_STD bad_alloc)
{
    /* _nh_malloc_dbg already calls _heap_alloc_dbg in a loop and calls _callnewh
       if the allocation fails. If _callnewh returns (very likely because no
       new handlers have been installed by the user), _nh_malloc_dbg returns NULL.
     
*/
    void *res = _nh_malloc_dbg( cb, 1, nBlockUse, szFileName, nLine );

    RTCCALLBACK(_RTC_Allocate_hook, (res, cb, 0));

    /* if the allocation fails, we throw std::bad_alloc */
    if (res == 0)
    {
        static const std::bad_alloc nomem;
        _RAISE(nomem);
    }

    return res;
}
這樣Crt會把此次分配內存的文件名和行號以及大小等記錄下來,最后當調用用_CrtDumpMemoryLeaks(); 時如果還沒釋放就會打印出來。
結果如下:
Detected memory leaks!
Dumping objects ->
f:\test\memleakchecker\memleakchecker\memleakchecker.cpp(23) : {108} normal block at 0x0003A1A8, 10 bytes long.
 Data: <          > CD CD CD CD CD CD CD CD CD CD 
f:\test\memleakchecker\memleakchecker\memleakchecker.cpp(22) : {107} client block at 0x0003A160, subtype 0, 10 bytes long.
 Data: <          > CD CD CD CD CD CD CD CD CD CD 
f:\test\memleakchecker\memleakchecker\memleakchecker.cpp(21) : {106} client block at 0x0003A120, subtype 0, 1 bytes long.
 Data: < > 00 
Object dump complete.

下面是一些注意事項:
(1) #define _CRTDBG_MAP_ALLOC 的作用
如果不定義這個宏, C方式的malloc泄露不會被記錄下來。

(2)數字{108} {107}的作用
表示第幾次分配, 你可以通過_CrtSetBreakAlloc程序運行到預定次數時暫停 ,比如
int _tmain(int argc, _TCHAR* argv[])
{
    _CrtSetBreakAlloc(108);

    char* p = new char();
    char* pp = new char[10];
    char* ppp = (char*)malloc(10);

    _CrtDumpMemoryLeaks();

    return 0;
}

(3)如果程序有多個出口或是有涉及到全局變量, 可以通過_CrtSetDbgFlag 設置標志讓程序退出時自動打印泄露 , 比如
int _tmain(int argc, _TCHAR* argv[])
{
    _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

    char* p = new char();
    char* pp = new char[10];
    char* ppp = (char*)malloc(10);

    return 0;
}

(4)我們知道宏替代是最粗暴的方式, 所以盡量把下面new的替代宏放到每個Cpp里而不是放到一個通用的頭文件中, 實際上MFC也是這么做的
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif

(5)上面的operator new只能照顧到最普通的new, 實際上operator new是有任意多種重載方式, 只需要確保第一個參數是表示大小。 比如下面的placement new就會編譯失敗, 因為宏替代后格式不符合要求了, 所以如果你的CPP用了非標準的new, 就不要加入new的檢測宏了。
#include <new>

#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif


int _tmain(int argc, _TCHAR* argv[])
{
    _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

    char* p = new char();
    char* pp = new char[10];
    char* ppp = (char*)malloc(10);

    char d;
    char* p1 = new(&d) char('a');

    return 0;
}

(6)因為STL里map內的tree用到了placement new,  所以如果你這樣用會編譯失敗:
#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif

#include <map>
你應該把 #include <map>放到 宏定義的前面。

(7) 如果你在宏 #define new DEBUG_CLIENTBLOCK 之后再聲明或定義 operator new函數, 都會因為宏替代而編譯失敗。
而STL的xdebug文件恰恰申明了operator new函數, 所以請確保new的替代宏放在所有include頭文件的最后, 尤其要放在STL頭文件的后面。
//MyClass.cpp
#include "myclass.h"
#include <map>
#include <algorithm>

#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif

MyClass::MyClass()
{
    char* p = new char('a');
}

(8)如果你覺得上面的這種new替代宏分散在各個CPP里太麻煩, 想把所有的東西放到一個通用頭文件里,請參考下面定義的方式:
//MemLeakChecker.h 
#include <map>
#include <algorithm>
//other STL file

#ifdef _DEBUG
#define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
#define DEBUG_CLIENTBLOCK
#endif
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif
 
(9)簡單判斷某個獨立函數有沒有內存泄露可以用下面的方法:
class DbgMemLeak
{
    _CrtMemState m_checkpoint;

public:
    explicit DbgMemLeak() 
    {   
        _CrtMemCheckpoint(&m_checkpoint); 
    };

    ~DbgMemLeak()
    {
        _CrtMemState checkpoint;
        _CrtMemCheckpoint(&checkpoint);
        _CrtMemState diff;
        _CrtMemDifference(&diff, &m_checkpoint, &checkpoint);
        _CrtMemDumpStatistics(&diff);
        _CrtMemDumpAllObjectsSince(&diff);
    };
};


int _tmain(int argc, _TCHAR* argv[])
{
    DbgMemLeak check;
    {
        char* p = new char();
        char* pp = new char[10];
        char* ppp = (char*)malloc(10);
    }

    return 0;
}

(10) 其實知道了原理, 自己寫一套C++內存泄露檢測也不難, 主要是重載operator new和operator delete, 可以把每次內存分配情況都記錄在一個Map里, delete時刪除記錄, 最后程序退出時把map里沒有delete的打印出來。 當然我們知道Crt在實現new時一般實際上調的是malloc, 而malloc可能又是調HeapAlloc,而HeapAlloc可能又是調用RtlAllocateHeap, 所以理論上我們可以在這些函數的任意一層攔截和記錄。但是如果你要實現自己的跨平臺內存泄露檢測,還是重載operator new吧。

posted on 2013-02-25 22:13 Richard Wei 閱讀(7761) 評論(2)  編輯 收藏 引用 所屬分類: C++

FeedBack:
# re: C++中基于Crt的內存泄露檢測
2013-02-26 08:46 | 朱峰everettjf
不錯,學習了  回復  更多評論
  
# re: C++中基于Crt的內存泄露檢測
2013-02-26 13:30 | Render Donkey
mark一下  回復  更多評論
  
# re: C++中基于Crt的內存泄漏檢測
2014-08-14 12:29 | memleak.in
不錯,學習了!  回復  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲国产裸拍裸体视频在线观看乱了中文| 亚洲人成网站在线观看播放| 欧美激情一区二区三区全黄| 国产精品久久久久久久久婷婷| 久久夜色精品国产噜噜av| 欧美日韩国产精品一区二区亚洲| 久久久噜噜噜| 国产精品日日摸夜夜摸av| 亚洲电影下载| 狠狠色丁香婷婷综合久久片| 一区二区三区国产在线| 亚洲日韩中文字幕在线播放| 欧美在线www| 欧美在线看片| 国产精品久久福利| 亚洲乱码国产乱码精品精98午夜| 亚洲国内自拍| 久久久亚洲高清| 久久综合精品国产一区二区三区| 国产精品亚洲综合色区韩国| 一区电影在线观看| 亚洲特色特黄| 欧美午夜片在线免费观看| 亚洲经典视频在线观看| 亚洲人人精品| 欧美精品一卡二卡| 亚洲精品1区| 亚洲精品乱码久久久久久| 美女诱惑一区| 亚洲黄色大片| 日韩一级免费| 国产精品久久久久9999高清| 中文av一区二区| 新67194成人永久网站| 国产精品夜色7777狼人| 亚洲欧美日韩精品综合在线观看| 欧美一区免费视频| 国产最新精品精品你懂的| 久久爱91午夜羞羞| 美日韩精品视频| 亚洲欧洲另类国产综合| 欧美精品精品一区| 夜夜狂射影院欧美极品| 午夜久久福利| 国产自产v一区二区三区c| 久久久亚洲精品一区二区三区| 免费亚洲一区二区| 一本久道综合久久精品| 国产精品高潮呻吟视频| 欧美一区免费视频| 欧美国产第一页| 中国日韩欧美久久久久久久久| 国产精品久久久久毛片大屁完整版| 午夜影视日本亚洲欧洲精品| 免费中文字幕日韩欧美| 亚洲最新合集| 国产一区观看| 欧美成人a视频| 亚洲愉拍自拍另类高清精品| 久久夜色撩人精品| 亚洲美女在线一区| 国产精品一区在线观看| 美女被久久久| 亚洲一区国产| 亚洲高清久久久| 久久黄金**| 一区二区欧美国产| 国产主播精品| 欧美午夜宅男影院| 美女精品在线| 亚洲免费综合| 亚洲国产欧美不卡在线观看| 欧美一级黄色网| 日韩亚洲在线观看| 国产日本欧美一区二区三区| 欧美激情一区二区三区高清视频| 香蕉久久夜色精品国产| 亚洲欧洲精品一区二区| 久久―日本道色综合久久| 在线一区二区三区四区| 黄色欧美成人| 国产精品家庭影院| 欧美激情精品久久久久久蜜臀| 亚欧成人在线| 亚洲一级片在线看| 亚洲日本理论电影| 欧美成人午夜激情在线| 久久久精品动漫| 性一交一乱一区二区洋洋av| 一区二区电影免费观看| 亚洲国产精品毛片| 韩国精品一区二区三区| 国产精品免费看| 欧美视频网址| 欧美日韩大片| 欧美美女喷水视频| 欧美xx视频| 免费一区视频| 免费高清在线一区| 久久久久久久999精品视频| 亚洲你懂的在线视频| 日韩一级片网址| 亚洲欧洲午夜| 亚洲精品三级| 日韩午夜在线电影| 最新国产成人av网站网址麻豆| 男女精品网站| 毛片一区二区| 女同一区二区| 欧美高潮视频| 最新成人av在线| 亚洲精品久久久一区二区三区| 欧美高清视频免费观看| 欧美激情一区在线观看| 欧美黄色aaaa| 亚洲国产国产亚洲一二三| 亚洲激情不卡| 一本久久a久久免费精品不卡| 99国产成+人+综合+亚洲欧美| 一本色道久久| 午夜精品久久久久久久久久久久久 | 亚洲美女中出| 一区二区三区国产精华| 亚洲视频一起| 午夜精品视频在线观看一区二区| 午夜精品久久久久| 久久精品视频va| 欧美成人一区二区三区| 亚洲电影第1页| 亚洲伦理自拍| 亚洲欧美亚洲| 久久综合影音| 欧美日韩在线第一页| 国产精品日韩在线| 在线播放日韩专区| 99国产精品| 欧美在线啊v一区| 免费欧美电影| 日韩亚洲精品在线| 午夜精品久久久| 久久婷婷影院| 欧美日本在线看| 国产欧美日韩另类一区| 红桃视频国产精品| 99香蕉国产精品偷在线观看| 午夜精品999| 欧美h视频在线| 亚洲最新视频在线| 久久久欧美精品| 欧美视频二区36p| 激情五月综合色婷婷一区二区| 亚洲精品欧美日韩| 欧美一区国产一区| 亚洲韩国青草视频| 欧美专区第一页| 欧美日韩国产色综合一二三四| 国产日产欧产精品推荐色| 亚洲第一狼人社区| 亚洲欧美日韩爽爽影院| 蜜臀av一级做a爰片久久| 夜夜嗨av一区二区三区| 久久综合九色99| 国产精品一区二区a| 亚洲日本aⅴ片在线观看香蕉| 欧美一级久久| 日韩午夜黄色| 蜜臀av性久久久久蜜臀aⅴ四虎| 国产精品拍天天在线| 亚洲乱码国产乱码精品精可以看| 欧美影院午夜播放| 亚洲另类在线一区| 六月婷婷久久| 国模私拍视频一区| 欧美有码在线观看视频| 99精品欧美一区| 欧美黄色精品| 亚洲国产美国国产综合一区二区| 欧美一区二区三区在线看 | 老司机亚洲精品| 亚洲影院色无极综合| 欧美日韩国产综合在线| 亚洲高清不卡| 久热精品在线| 欧美一级片久久久久久久| 欧美小视频在线| 99香蕉国产精品偷在线观看| 欧美高潮视频| 欧美va天堂| 亚洲精品视频一区| 欧美aa国产视频| 老司机精品视频一区二区三区| 一区在线播放| 免费观看30秒视频久久| 久久蜜桃资源一区二区老牛| 国内视频一区| 久久午夜影视| 久久精品亚洲乱码伦伦中文| 国产综合精品一区| 美国十次了思思久久精品导航| 久久久久一区二区|