• <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>

            loop_in_codes

            低調做技術__歡迎移步我的獨立博客 codemaro.com 微博 kevinlynx

            自己寫內存泄露檢測庫

            author: kevin lynx

            這個內存泄露工具最基本的原理就是利用宏替換掉標準的malloc、free(暫不考慮其他內存分配函數,
            如realloc、strdup),記錄下每次內存分配和釋放動作。因為宏的處理發生在預處理階段,所以可以
            很容易地用你自己的malloc函數替換掉標準的malloc。例如:

            /* lib.h */
            #define malloc my_malloc
            #define free my_free 

            /* lib.c */
            /* disable these macro in this compile unit */
            #undef malloc
            #undef free 

            static int count = 0

            void *my_malloc( size_t size )
            {
                
            ++count;
                
            return malloc( size );
            }
             

            void my_free( void *a )
            {
                
            --count;
                free( a );
            }
             


            要使用以上代碼,用戶在使用時就需要包含lib.h,從而可以使用宏將用戶自己寫的malloc替換
            為my_mallo。當程序退出時,如果count大于0,那么可以肯定的是有內存泄露。當然,如果
            count為負數,則很可能對同一個指針進行多次free。

            但是以上代碼的功能太局限了。一個真正的內存泄露檢測庫(工具),至少需要報告泄露的代碼
            文件、函數、行數等信息。當然,如果能報告調用堆棧,就更好了。不過這就依賴于具體的平臺,
            需要使用特定的系統接口才可以獲取出。

            要實現以上功能也很簡單,只需要在每次調用malloc的時候,通過編譯器預定義宏__FILE__、
            __LINE__、__FUNCTION__(__func__)就可以得到文件名、函數、行號等信息。將這些信息保存
            起來,然后在free的時候移除相應的信息即可。

            最簡單的實現方式,就是保存一個表,表里記錄著每次分配內存的信息:

             

            struct memRecord
            {
                
            char file[MAX_FILE_NAME];
                
            char func[MAX_FUNC_NAME];
                size_t lineno;
                
            void *address;
                size_t size;
            }


            struct memRecord mem_record[MAX_RECORD]; 

             

            但是,通過單單一個free函數的void*參數,如何獲取出對應的分配記錄呢?難道:

            for( size_t i = 0; i < MAX_RECORD; ++ i )
            {
                
            if( address == mem_record[i].address ) 
                
            {
                    
            /* shit */
                }

            }
             

             

            雖然可行,但是很stupid。這里提供一個小技巧:

             

            void *my_malloc( size_t size )
            {
                
            void *= malloc( size + sizeof( size_t ) );
                
            return (char*)a + sizeof( size_t );
            }
             

            void my_free( void *a )
            {
                
            /* actually, 'a' is not the real address */
                
            char *= ((char*)a - sizeof( size_t ) );    
                free( p );
            }

             

            意思就是說,我多分配了4字節內存(sizeof( size_t ) ),用于保存這次分配記錄在mem_record
            中被保存的索引。在釋放內存的時候,通過一些地址偏移計算,就可以獲取出真正的系統malloc
            返回的地址,從而安全釋放(別給我說這里的計算存在平臺和編譯器的限制,沒認真看文章的SB才說)。

            另一個問題是,我們如何處理每次分配釋放時,對于分配記錄那個數據結構,也就是mem_record。
            每一次free的時候,移除的記錄可能位于mem_record的任何位置。一定時間后,mem_record內部
            將出現很多漏洞(已經沒用的數組位置)。解決這個問題最直接當然還是最stupid的方法,就是每次
            free移除記錄時重新整理一遍mem_record。如果你這樣做了,那你的malloc/free比微軟的還慢。

            我的解決方法是:
            size_t free_index[MAX_RECORD];
            用于保存這些出現漏洞的index。每一次free移除記錄時,就把這個記錄對應的inex保存進來,表示
            這個index指向的mem_record[]可用。每一次malloc的時候,先從這里取index,如果這里沒有,那
            可以直接從mem_record的末尾取。

            具體細節就不闡述了,典型的空間換時間方法。整個庫很簡單,代碼100來行。我也只進行過粗略的
            測試。我肯定這100來行代碼是有問題的,相信自己的代碼存在問題是對bug的一種覺悟,哈哈哈。

            這個東西只檢測C語言的內存泄露,其實要檢測C++的也很簡單,只需要重載new和delete就可以了。

            要放春節假了,在公司的最后幾個小時實在無聊,才做了這個東西,前后花了1個多小時,寫起來感覺
            不錯。

             

             

            代碼下載

             

            posted on 2009-01-23 17:43 Kevin Lynx 閱讀(4402) 評論(5)  編輯 收藏 引用 所屬分類: c/c++

            評論

            # re: 自己寫內存泄露檢測庫 2009-01-23 22:53 jims

            本人一直博主學習  回復  更多評論   

            # re: 自己寫內存泄露檢測庫 2009-01-23 23:04 adon

            char *str = (char*) malloc( 100 );
            char *str2 = (char*) malloc( 111 );
            str = str2;
            free(str);
            free(str);
            getchar();

            Memory leak report by cmlc, a tiny c memory leak checking library.
            Detected 0 memory leaks.

            似乎在free上出了點問題  回復  更多評論   

            # re: 自己寫內存泄露檢測庫 2009-01-23 23:28 adon

            static void cmlc_remove_record( size_t index )
            {
            if( fi_tail < MAX_RECORD - 1 )
            {
            free_index[fi_tail++] = index;
            free(mem_record[index].address);
            mem_record[index].address = 0; /* to identify this record has been removed */
            }
            }

            void cmlc_free( void *address )
            {
            struct memory *mem = (struct memory*)( (char*)address - sizeof( size_t ) );
            cmlc_remove_record( mem->index );
            // free( mem ); //注釋的free,移到cmlc_remove_record中
            }  回復  更多評論   

            # re: 自己寫內存泄露檢測庫 2009-01-23 23:55 萬連文

            需要考慮多線程,否則太不安全了,沒有實際意義。  回復  更多評論   

            # re: 自己寫內存泄露檢測庫 2009-01-24 20:55 陳梓瀚(vczh)

            微軟的編譯器僅需在cpp開始的地方:
            #define _CRTDBG_MAP_ALLOC
            #include <stdlib.h>
            #include <crtdbg.h>

            當你認為東西都是放完了以后調用
            _CrtDumpMemoryLeaks();

            東西就回到output窗口去了。  回復  更多評論   

            一本一道久久精品综合| 欧美精品国产综合久久| 国内精品久久久久久麻豆| 日韩精品久久久肉伦网站| 久久91精品国产91久久小草| 亚洲精品国产第一综合99久久| 伊人久久大香线焦AV综合影院| 亚洲午夜久久久影院| 爱做久久久久久| 久久夜色tv网站| 91精品国产综合久久香蕉| 久久精品欧美日韩精品| 99久久99这里只有免费的精品| 狠狠色丁香久久婷婷综合| 人人狠狠综合88综合久久| 久久无码精品一区二区三区| 亚洲国产精品久久| 精品久久久久国产免费| 久久国产欧美日韩精品免费| 久久久久亚洲精品男人的天堂| 色婷婷综合久久久久中文| 99久久国产综合精品麻豆| 热久久这里只有精品| 国产亚洲色婷婷久久99精品91| 国产激情久久久久影院老熟女| 久久久久久av无码免费看大片| 久久综合久久伊人| 久久国产精品-国产精品| 久久久久久噜噜精品免费直播| 久久综合亚洲色HEZYO社区| 国内精品伊人久久久久AV影院| 国产日产久久高清欧美一区| 四虎亚洲国产成人久久精品| 精品久久久噜噜噜久久久| 四虎国产精品免费久久| 亚洲一区二区三区日本久久九| 伊人情人综合成人久久网小说| 国产免费久久精品丫丫| 99麻豆久久久国产精品免费| 日日噜噜夜夜狠狠久久丁香五月 | 久久人人爽人人爽人人片AV麻豆|