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