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

隨筆-91  評(píng)論-137  文章-0  trackbacks-0
上一篇中我們已經(jīng)實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的內(nèi)存池,可以申請(qǐng)更大塊的內(nèi)存塊來減少申請(qǐng)小塊內(nèi)存塊時(shí)產(chǎn)生的內(nèi)存碎片。

在本篇中,我們需要為其加入內(nèi)存泄漏的檢測(cè)代碼,以此來檢測(cè)代碼編寫過程中的疏忽帶來的內(nèi)存泄漏。(callstack的顯示暫時(shí)僅支持Windows)

一、內(nèi)存泄漏檢測(cè)
首先,改寫obj和block結(jié)構(gòu),在obj中加入一個(gè)域released表示這個(gè)chunk是否被釋放
 1     struct obj
 2     {
 3 #ifdef _DEBUG
 4         bool      released;
 5 
 6 #if defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) // Only windows can get callstack
 7 #define CALLSTACK_MAX_DEPTH 30
 8         UINT_PTR  callStack[CALLSTACK_MAX_DEPTH];
 9         DWORD     dwCallStackDepth; // Real depth
10 #endif
11 
12 #endif
13         obj*      next;
14     };
15 
16     struct block
17     {
18         block*    next;
19         void*     data;
20 #ifdef _DEBUG
21         size_type size;
22 #if defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
23         UINT_PTR  callStack[CALLSTACK_MAX_DEPTH];
24         DWORD     dwCallStackDepth;
25 #endif
26 #endif
27     };
其中的callstack部分將在下一節(jié)中介紹

然后,我們?cè)黾右粋€(gè)結(jié)構(gòu)
1 #ifdef _DEBUG
2     struct use
3     {
4         obj* data;
5         use* next;
6     };
7 #endif
其中data域指向了一塊分配出去的小內(nèi)存塊,next域形成了一張鏈表。

然后,我們添加一個(gè)成員變量來保存這張鏈表,以及一個(gè)函數(shù)來將一個(gè)chunk插入這張鏈表
#ifdef _DEBUG
    use*      use_list;
#endif

#ifdef _DEBUG
inline void MemoryPool::addUseInfo(obj* ptr)
{
    use* p = (use*)malloc(sizeof(use));
    p->data = ptr;
    p->next = use_list;
    use_list = p;
}
#endif

然后,我們來改寫refill函數(shù)使其在分配內(nèi)存塊時(shí)打上released標(biāo)記,并將每個(gè)分配的內(nèi)存塊記錄下來
 1 void* MemoryPool::refill(int i, void(*h)(size_type))
 2 {
 3     const int count = 20;
 4     const int preSize = (i + 1) * ALIGN + headerSize;
 5     char* p = (char*)malloc(preSize * count);
 6     while(p == 0)
 7     {
 8         h(preSize * count);
 9         p = (char*)malloc(preSize * count);
10     }
11     block* pBlock = (block*)malloc(sizeof(block));
12     while(pBlock == 0)
13     {
14         h(sizeof(block));
15         pBlock = (block*)malloc(sizeof(block));
16     }
17     pBlock->data = p;
18     pBlock->next = free_list;
19     free_list = pBlock;
20 
21     obj* current = (obj*)p;
22 #ifdef _DEBUG
23     addUseInfo(current);
24     current->released = false;
25 #endif
26     current = (obj*)((char*)current + preSize);
27     for(int j = 0; j < count - 1; ++j)
28     {
29 #ifdef _DEBUG
30         addUseInfo(current);
31         current->released = true;
32 #endif
33         current->next = chunk_list[i];
34         chunk_list[i] = current;
35         current = (obj*)((char*)current + preSize);
36     }
37     return (char*)p + headerSize;
38 }
其中的headerSize跟callstack有關(guān),將在下一節(jié)中介紹。

當(dāng)然,在deallocate時(shí)要將此內(nèi)存塊的released標(biāo)記打?yàn)閠rue
 1 void MemoryPool::deallocate(void* p, size_type n)
 2 {
 3     if(p == 0) return;
 4     if(n > MAX_BYTES)
 5     {
 6         free(p);
 7         return;
 8     }
 9     const int i = INDEX(ROUND_UP(n));
10 #ifdef _DEBUG
11     p = (char*)p - (int)headerSize;
12     obj* ptr = reinterpret_cast<obj*>(p);
13     if (ptr->released) throw error<char*>("chunk has already released", __FILE__, __LINE__);
14     ptr->released = true;
15 #endif
16     reinterpret_cast<obj*>(p)->next = chunk_list[i];
17     chunk_list[i] = reinterpret_cast<obj*>(p);
18 }

OK,現(xiàn)在已經(jīng)有模有樣了,可以松口氣了。接下來是最重要的部分,在MemoryPool析構(gòu)時(shí)檢測(cè)這個(gè)Pool內(nèi)的use_list中是否有chunk的released標(biāo)記為true(內(nèi)存泄漏了)
 1 MemoryPool::~MemoryPool()
 2 {
 3 #ifdef _DEBUG
 4     while (use_list)
 5     {
 6         use *ptr = use_list, *next = use_list->next;
 7         if (!ptr->data->released)
 8         {
 9             obj* pObj = ptr->data;
10             Console::SetColor(truefalsefalsetrue);
11             throw error<char*>("chunk leaked", __FILE__, __LINE__);
12         }
13         free(ptr);
14         use_list = next;
15     }
16 #endif
17     clear();
18 }
其實(shí)說來也容易,只需要檢測(cè)每個(gè)chunk的released標(biāo)記是否為true就行了,而最后的clear函數(shù)是以前析構(gòu)函數(shù)的代碼,用來釋放所有申請(qǐng)的block和大塊的chunk。

OK,現(xiàn)在我們已經(jīng)可以檢測(cè)出沒有被deallocate的chunk了。

二、callstack
首先,我們先來看一個(gè)Windows API,“CaptureStackBackTrace”這個(gè)API通過傳入的一個(gè)數(shù)組來得到一組地址。當(dāng)然有這個(gè)API并不夠,我們還需要知道是哪個(gè)文件的第幾行。“SymGetSymFromAddr64”這個(gè)API用來獲取某個(gè)地址對(duì)應(yīng)的函數(shù)名,“SymGetLineFromAddr64”這個(gè)API則是用來獲取某個(gè)地址對(duì)應(yīng)的文件名和行號(hào)的,這兩個(gè)函數(shù)的32位版本則是不帶64的。有了這些Windows API,我們就可以很輕松的獲取到當(dāng)前函數(shù)的調(diào)用堆棧了,主要的功勞還是要?dú)w功于Windows強(qiáng)大的dbghelp。

最后,完整的代碼你可以在http://code.google.com/p/qlanguage/中找到。
posted on 2013-01-19 20:09 lwch 閱讀(1968) 評(píng)論(0)  編輯 收藏 引用 所屬分類: STL
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美一区亚洲二区| 久久在线精品| 亚洲免费影院| 欧美日韩在线观看视频| 一区二区三区欧美在线| 亚洲私拍自拍| 狠狠爱综合网| 亚洲国产三级网| 欧美日韩精品综合在线| 亚洲欧美不卡| 久久精品国产免费看久久精品| 韩国v欧美v日本v亚洲v| 亚洲电影免费观看高清| 欧美日韩亚洲一区二区三区在线 | 韩国美女久久| 欧美福利一区| 国产精品成人观看视频国产奇米| 欧美亚洲尤物久久| 老司机亚洲精品| 亚洲一级特黄| 另类av导航| 亚洲欧美在线网| 久久久久久久97| 亚洲视屏在线播放| 久久精品综合网| 一区二区三区精品视频| 欧美在线一级视频| 亚洲视频一区在线观看| 欧美在线一区二区| 亚洲无玛一区| 美女啪啪无遮挡免费久久网站| 亚洲自拍偷拍视频| 欧美成人四级电影| 久久噜噜亚洲综合| 国产精品久久久久婷婷| 亚洲高清在线精品| 国产有码一区二区| 一区二区三区日韩欧美精品| 91久久久久久| 久久精品亚洲一区二区三区浴池| 亚洲手机成人高清视频| 欧美一区二区三区免费视| 久久综合99re88久久爱| 欧美在线观看一区| 欧美日韩色婷婷| 免费观看久久久4p| 国产婷婷一区二区| av成人免费| 亚洲精品影院在线观看| 久久精品一二三区| 久久久精品五月天| 国产亚洲毛片| 亚洲欧美在线视频观看| 亚洲一区二区精品视频| 欧美日韩成人精品| 亚洲激情女人| av成人动漫| 欧美日韩国产丝袜另类| 亚洲黄网站在线观看| 亚洲激情一区二区三区| 老司机午夜精品视频| 欧美成人一区二区在线| 亚洲丶国产丶欧美一区二区三区| 久久久久91| 嫩草国产精品入口| 亚洲国产婷婷综合在线精品 | 久久琪琪电影院| 嫩草成人www欧美| 亚洲国产精品视频| 欧美国产另类| 亚洲美女中出| 亚洲欧美中文字幕| 国产网站欧美日韩免费精品在线观看| 亚洲免费人成在线视频观看| 销魂美女一区二区三区视频在线| 国产精品入口日韩视频大尺度| 亚洲与欧洲av电影| 久久精品国产免费观看| 一区二区三区在线观看视频| 久久久欧美精品sm网站| 亚洲国产精品一区二区第一页| 日韩视频免费在线| 国产精品sm| 欧美在线一二三| 亚洲国产成人久久综合| 亚洲香蕉成视频在线观看| 国产精品社区| 麻豆91精品91久久久的内涵| 亚洲精品视频在线观看免费| 欧美一区二区三区的| 精品不卡一区二区三区| 欧美日本免费| 久久国产加勒比精品无码| 欧美激情小视频| 性久久久久久久久| 亚洲激情二区| 国产精品久久久久久亚洲调教| 久久成人免费日本黄色| 最新中文字幕亚洲| 久久久7777| 一区二区三区国产精华| 国内视频一区| 欧美午夜性色大片在线观看| 久久久久一本一区二区青青蜜月| 99riav1国产精品视频| 另类图片国产| 午夜欧美精品久久久久久久| 亚洲黄页视频免费观看| 国产精品推荐精品| 欧美日韩高清在线播放| 久久精品天堂| 久久久久久日产精品| 艳妇臀荡乳欲伦亚洲一区| 精品成人一区二区| 国产精品va在线| 欧美精品一区二区三区一线天视频| 午夜精品视频| 亚洲视屏在线播放| 最新成人av在线| 欧美国产第二页| 久久婷婷丁香| 久久久久久久综合| 欧美一级片一区| 亚洲一区二区三区四区五区午夜 | 国产精品久久久久久久久动漫| 噜噜噜91成人网| 久久精品在线视频| 欧美一区二区三区四区在线| 在线亚洲免费视频| 99国产精品久久久久久久成人热 | 卡一卡二国产精品| 久久精品一区二区三区不卡牛牛| 午夜亚洲影视| 性欧美大战久久久久久久免费观看| 999亚洲国产精| 日韩午夜激情电影| 亚洲伦理在线免费看| 亚洲欧洲一区二区在线观看| 一区二区在线观看视频在线观看| 国产一区二区精品在线观看| 国产免费观看久久黄| 国产精品女同互慰在线看| 国产精品三上| 国产午夜精品一区二区三区欧美| 国产精品网曝门| 国产私拍一区| 在线不卡中文字幕| 亚洲国产精品va在线观看黑人 | 国产亚洲欧洲| 狠狠色综合网站久久久久久久| 国产一区二区三区自拍| 国内精品国语自产拍在线观看| 国产午夜精品一区理论片飘花 | 欧美一区二区三区视频| 欧美在线啊v| 欧美v日韩v国产v| 亚洲黄网站黄| 亚洲少妇中出一区| 新狼窝色av性久久久久久| 久久国产天堂福利天堂| 老妇喷水一区二区三区| 欧美国产日韩一区二区| 欧美性事免费在线观看| 国产欧美在线播放| 亚洲国产成人在线| 亚洲特级片在线| 久久久蜜臀国产一区二区| 亚洲高清一区二区三区| 99这里有精品| 久久精品国产视频| 欧美连裤袜在线视频| 国产日韩欧美日韩大片| 亚洲精品1区2区| 亚洲欧美日韩人成在线播放| 看片网站欧美日韩| 99在线视频精品| 久久亚洲私人国产精品va| 欧美日韩一区二区三区在线 | 亚洲精品乱码久久久久久蜜桃麻豆| 久久国产主播精品| 欧美激情女人20p| 亚洲一区二区三区视频播放| 久久综合九色| 国产欧美精品在线| 亚洲精品综合精品自拍| 久久成人18免费网站| 亚洲精品免费在线观看| 欧美中文在线免费| 欧美视频中文字幕| 最近中文字幕mv在线一区二区三区四区 | 欧美在线日韩在线| 欧美日韩在线另类| 亚洲福利av| 久久久精品免费视频| 一区二区三区欧美激情| 欧美xart系列在线观看| 国内激情久久| 久久国产精品亚洲77777| aⅴ色国产欧美| 欧美成熟视频|