C語言記憶體洩露檢測--Memwatch
阿新 • • 發佈:2019-01-27
專案:迅雷下載庫記憶體洩露檢測
作者:曾金龍
供職:深圳迅雷網路技術股份有限公司
領域:迅雷下載庫
時間: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轉移到聊哪件衣服好看了,恩,不錯。