96
技術社區[雲棲]
C語言內存泄露檢測--Memwatch
項目:迅雷下載庫內存泄露檢測
作者:曾金龍
供職:深圳迅雷網絡技術股份有限公司
領域:迅雷下載庫
時間:2014-07-26
迅雷的移動下載庫是用C語言編寫的,為了能夠橫跨歐亞非拉(ios,android,還有諾基亞的什麼係統來著,對了symban)和性能,我們廠的下載庫就選擇了C,然後在C代碼裏麵使用各種宏,預編譯等來達到一 個下載庫,多平台使用。不過平台相關的都已經約束在了一個叫common的庫裏麵的一個子模塊裏麵了。這極大的解放了我廠的碼農朋友。
但是C畢竟是C,在聊起C的時候,我們組最喜歡說的是,我們權限最大,想幹啥幹啥。最悲痛的是,測試妹子過來了,然後說各種問題,但是logcat都捕獲不到,或者有時候崩潰了但是沒有tombstone,等。其實,C最大的危險就是內存泄露。。。因為C的內存泄露,我和測試妹子的感情最近變得更加的親密而又微妙。。。
老大發話了,必須解決所有C內存泄露。。。
在我下寫我負責的數據存儲模塊的時候,我就動了一個小技巧,就能夠把本模塊的內存泄露全部給檢測出來,而我這樸素的思想其實也是其他內存泄露檢測工具的靈魂,隻是,老大嫌我的太樸素了。
我的做法很簡單,每次malloc內存的時候不是調用係統的malloc,而是調用我的malloc,取名為fc_malloc(因為我的模塊叫file_cache),free則調用fc_free。具體代碼如下:
#define fc_malloc(size) fc_malloc_imp(size,__FILE__,__LINE__) #define fc_free(ptr) fc_free_imp(ptr) typedef struct mem_log{ void* addr; char* file; int line; }memlog; #ifdef _LOGGER static list g_mem_list #endif // _LOGGER void init_module() { #ifdef _LOGGER list_init(&g_mem_list); #endif } void uninit_module() { #ifdef _LOGGER list_for_each(g_mem_list,v) { memlog* iterm=(memlog*)LIST_VALUE(v); printf("%s,%d,%x\n",iterm->file,iterm->line,iterm->addr);//output the memory not free.. free(iterm); } list_clear(&g_mem_list); #endif // _LOGGER } void* fc_malloc_imp(size_t size,char* file,int line) { void* ptr=malloc(size); #ifdef _LOGGER if(ptr!=NULL) { memlog* iterm = (memlog*)malloc(sizeof(memlog)); iterm->addr=ptr; iterm->file=file; iterm->line=line; list_insert(&g_mem_list,iterm); } #endif // _LOGGER return ptr; } void fc_free_imp(void* ptr) { #ifdef _LOGGER if(ptr!=NULL) { list_erase_by_addr(&g_mem_list,ptr);//in this funciton we need free the memlog iterm memory. } #endif // _LOGGER free(ptr); }
卻是很簡單,說白了就是用一個鏈表去等級下每次malloc的地址信息,當然為了好定位,包含文件和行信息,然後在模塊卸載的時候,就可以打印出哪些內存還沒有被釋放。這樣對於檢查內存泄露,已經達到目的了,很簡單吧。有用的東西都是很簡單,但很巧妙。
在老大說我應該去看下現有的內存檢測工具之前,我覺得我 的這個“創作”已經幫了我解決了所有的內存泄露問題,至少,我和測試妹子的關係從聊bug轉移到聊哪件衣服好看了,恩,不錯。
最後更新:2017-04-03 05:39:33