內存泄漏是在不帶有垃圾回收(garbage Collection)機制的語言中,如c/c++,經常出現的問題。由于缺乏垃圾回收,程序員需要自行管理分配的內存并進行釋放。內存泄漏的根本原因在于程序未能釋放申請的內存。
{ void?*p1?=?malloc(10); void?*p2?=?malloc(20); free(p1); }
上述代碼片段中,申請了兩塊內存p1和p2,但只釋放了p1,而未釋放p2,導致了內存泄漏。
內存泄漏可能會導致以下后果:
隨著程序運行時間的增長,未釋放的內存會逐漸累積,導致進程堆中的可用內存越來越少,最終耗盡。這將導致后續的運行時代碼無法成功分配所需的內存空間。
內存泄漏如何解決?
方案一 引入gc,從語言層面解決內存泄漏;
方案二 當發生內存泄漏的時候,能夠精準的定位代碼那個文件、那個函數、哪一行所引起的。
我們實現的是方案二,核心需求有兩個。
需求1:能夠檢測出內存泄漏
需求2:能夠指出是由代碼的哪個文件、哪個函數、哪一行引起的內存泄漏
內存泄漏檢測如何實現?
內存泄漏檢測實現的核心思想就是對系統的malloc/free進行hook,用我們自己的malloc/free代替系統調用,將free的地址和malloc的地址進行匹配,查看最后又哪些malloc沒有進行free,并將沒有free的malloc操作的代碼段地址進行記錄,通過代碼段定位所在的文件、函數、代碼行。
方案一
采用__libc_malloc, libc_free與__builtin_return_address。它們是gcc提供的函數。
__libc_malloc, libc_free用來代替malloc/free。可以用來實現hook。需要注意的是,我們實現的malloc/free函數,內部會有一些函數如printf,fopen,需要防止它們會嵌套調用malloc/free。
__builtin_return_address,能夠返回調用所在函數的代碼段的地址。能夠定位內存泄漏的具體位置。
malloc的時候,創建一個文件,文件名使用申請內存的地址,并記錄申請該內存的代碼段的地址;free的時候,刪除對應的文件。
#include? #include? #include? ? int?enable_malloc_hook?=?1; extern?void?*__libc_malloc(size_t?size); ? int?enable_free_hook?=?1; extern?void?*__libc_free(void?*p); ? void?*malloc(size_t?size)?{ ? ????if?(enable_malloc_hook)?{ ????????enable_malloc_hook?=?0; ? ????????void?*p?=?__libc_malloc(size); ? ????????void?*caller?=?__builtin_return_address(0); ? ????????char?buff[128]?=?{0}; ????????sprintf(buff,?"./mem/%p.mem",?p); ? ????????FILE?*fp?=?fopen(buff,?"w"); ????????fprintf(fp,?"[+%p]malloc?-->?addr:%p?size:%lu ",?caller,?p,?size); ????????fflush(fp); ? ????????enable_malloc_hook?=?1; ????????return?p; ????}?else?{ ? ????????return?__libc_malloc(size); ? ????} ????return?NULL; } ? void?free(void?*p)?{ ? ????if?(enable_free_hook)?{ ????????enable_free_hook?=?0; ????????char?buff[128]?=?{0}; ????????sprintf(buff,?"./mem/%p.mem",?p); ? ????????if?(unlink(buff)?printf("double?free:?%p ",?p); ????????} ? ????????__libc_free(p); ? ? ????????enable_free_hook?=?1; ????}?else?{ ????????__libc_free(p); ????} ? } ? //?gcc?-o?memleak_0?memleak_0.c?-g //?addr2line?-f?-e??memleak_0??-a?0x4006d8 int?main()?{ ? ? ????void?*p1?=?malloc(10); ????void?*p2?=?malloc(20); ? ????free(p1); ? ????void?*p3?=?malloc(30); ????void?*p4?=?malloc(40); ? ????free(p2); ????free(p4); ? ????return?0; }
方案二
使用宏定義, 開啟宏定義使用我們的版本,不開啟就使用系統的。可以方便debug。
內存泄漏檢測使用malloc_hook/free_hook, 定位內存泄漏位置,使用__FILE__, LINE.
#define?malloc(size)?malloc_hook(size,?__FILE__,?__LINE__) #define?free(p)?free_hook(p,?__FILE__,?__LINE__)
#include? #include? #include? ? void?*malloc_hook(size_t?size,?const?char?*file,?int?line)?{ ? ????void?*p?=?malloc(size); ? ????char?buff[128]?=?{0}; ????sprintf(buff,?"./mem/%p.mem",?p); ? ????FILE?*fp?=?fopen(buff,?"w"); ????fprintf(fp,?"[+%s:%d]malloc?-->?addr:%p?size:%lu ",?file,?line,?p,?size); ????fflush(fp); ? ????fclose(fp); ? ????return?p; ? } ? void?free_hook(void?*p,??const?char?*file,?int?line)?{ ? ????char?buff[128]?=?{0}; ????sprintf(buff,?"./mem/%p.mem",?p); ? ????if?(unlink(buff)?printf("double?free:?%p ",?p); ????????return; ????} ? ????free(p); ? } ? #define?malloc(size)???malloc_hook(size,?__FILE__,?__LINE__) ? #define?free(p)????free_hook(p,?__FILE__,?__LINE__) ? ? //?gcc?-o?memleak_0?memleak_0.c?-g //?addr2line?-f?-e??memleak_0??-a?0x4006d8 int?main()?{ ? ? ????void?*p1?=?malloc(10); ????void?*p2?=?malloc(20); ? ????free(p1); ? ????void?*p3?=?malloc(30);???//?memory?leak ????void?*p4?=?malloc(40); ? ????free(p2); ????free(p4); ????free(p4);?//?double?free ? ????return?0; ? }
檢測出兩個問題,一次內存泄漏 p3,一次double free p4。結果OK。
方案三
使用malloc.h中提供的hook: __malloc_hook, __free_hook.
這兩個hook,默認是malloc,free。
參考mtrace的做法,通過改變這兩個值來進行檢測。
#include? #include? #include? #include? ? typedef?void?*(*malloc_hoot_t)(size_t?size,?const?void?*caller); malloc_hoot_t?malloc_f; ? typedef?void?(*free_hook_t)(void?*p,?const?void?*caller); free_hook_t?free_f; ? void?mem_trace(void); void?mem_untrace(void); ? void?*malloc_hook_f(size_t?size,?const?void?*caller)?{ ? ????mem_untrace(); ????void?*ptr?=?malloc(size); ????//?printf("+%p:?addr[%p] ",?caller,?ptr); ????char?buff[128]?=?{0}; ????sprintf(buff,?"./mem/%p.mem",?ptr); ? ????FILE?*fp?=?fopen(buff,?"w"); ????fprintf(fp,?"[+%p]malloc?-->?addr:%p?size:%lu ",?caller,?ptr,?size); ????fflush(fp); ? ????fclose(fp); ???? ????mem_trace(); ????return?ptr; ? } ? void?free_hook_f(void?*p,?const?void?*caller)?{ ????mem_untrace(); ????//?printf("-%p:?addr[%p] ",?caller,?p); ? ????char?buff[128]?=?{0}; ????sprintf(buff,?"./mem/%p.mem",?p); ? ????if?(unlink(buff)?printf("double?free:?%p ",?p); ????} ???? ????free(p); ????mem_trace(); ? } ? void?mem_trace(void)?{ ? ????malloc_f?=?__malloc_hook; ????free_f?=?__free_hook; ? ????__malloc_hook?=?malloc_hook_f; ????__free_hook?=?free_hook_f; } ? void?mem_untrace(void)?{ ? ????__malloc_hook?=?malloc_f; ????__free_hook?=?free_f; ? } ? ? //?gcc?-o?memleak_0?memleak_0.c?-g //?addr2line?-f?-e??memleak_0??-a?0x4006d8 int?main()?{ ? ????mem_trace(); ????void?*p1?=?malloc(10); ????void?*p2?=?malloc(20); ? ????free(p1); ? ????void?*p3?=?malloc(30); ????void?*p4?=?malloc(40); ? ????free(p2); ????free(p4); ????mem_untrace(); ? ????return?0; ? }
方案四
使用mtrace
#include? #include? #include? #include? #include? ? //?gcc?-o?memleak_0?memleak_0.c?-g //?addr2line?-f?-e??memleak_0??-a?0x4006d8 int?main()?{ ? //?export?MALLOC_TRACE=./test.log ????mtrace(); ????void?*p1?=?malloc(10); ????void?*p2?=?malloc(20); ? ????free(p1); ? ????void?*p3?=?malloc(30); ????void?*p4?=?malloc(40); ? ????free(p2); ????free(p4); ????muntrace(); ? #endif ????return?0; ? }
方案五
使用dlsym對malloc,free進行hook。
#define?_GNU_SOURCE #include? ? #include? #include? #include? ? typedef?void?*(*malloc_t)(size_t?size); malloc_t?malloc_f; ? typedef?void?(*free_t)(void?*p); free_t?free_f; ? ? int?enable_malloc_hook?=?1; ? int?enable_free_hook?=?1; ? void?*malloc(size_t?size)?{ ? ????if?(enable_malloc_hook)?{ ????????enable_malloc_hook?=?0; ? ????????void?*p?=?malloc_f(size); ? ????????void?*caller?=?__builtin_return_address(0); ? ????????char?buff[128]?=?{0}; ????????sprintf(buff,?"./mem/%p.mem",?p); ? ????????FILE?*fp?=?fopen(buff,?"w"); ????????fprintf(fp,?"[+%p]malloc?-->?addr:%p?size:%lu ",?caller,?p,?size); ????????fflush(fp); ? ????????enable_malloc_hook?=?1; ????????return?p; ????}?else?{ ? ????????return?malloc_f(size); ? ????} ????return?NULL; } ? void?free(void?*p)?{ ? ????if?(enable_free_hook)?{ ????????enable_free_hook?=?0; ????????char?buff[128]?=?{0}; ????????sprintf(buff,?"./mem/%p.mem",?p); ? ????????if?(unlink(buff)?printf("double?free:?%p ",?p); ????????} ? ????????free_f(p); ? ? ????????enable_free_hook?=?1; ????}?else?{ ????????free_f(p); ????} ? } ? static?int?init_hook()?{ ? ????malloc_f?=?dlsym(RTLD_NEXT,?"malloc"); ? ????free_f?=?dlsym(RTLD_NEXT,?"free"); ? } ? //?gcc?-o?memleak_0?memleak_0.c?-ldl?-g //?addr2line?-f?-e??memleak_0??-a?0x4006d8 int?main()?{ ? ????init_hook(); ? ????void?*p1?=?malloc(10); ????void?*p2?=?malloc(20); ? ????free(p1); ? ????void?*p3?=?malloc(30); ????void?*p4?=?malloc(40); ? ????free(p2); ????free(p4); ? ????return?0; ? }
共享內存
mmap方法1
匿名mmap
#include? #include? #include? ? ? ? void?*shm_mmap_alloc(int?size)?{ ? ????void?*addr?=?mmap(NULL,?size,?PROT_READ|PROT_WRITE,? ????????MAP_ANON?|?MAP_SHARED,?-1,?0); ????if?(addr?==?MAP_FAILED)?{ ????????return?NULL; ????} ? ????return?addr; ? } ? int?shm_mmap_free(void?*addr,?int?size)?{ ? ????return?munmap(addr,?size); ? } ? ? int?main()?{ ? ????char?*addr?=?(char?*)shm_mmap_alloc(1024); ? ????pid_t?pid?=?fork(); ????if?(pid?==?0)?{ ????????//?child ????????int?i?=?0; ? ????????while(i?'a'?+?i++; ????????????addr[i]?=?' 主站蜘蛛池模板: 日韩国产成人精品视频人 | 手机看片自拍日韩日韩高清 | 久久黄色视屏 | 国产精品色内内在线播放 | 全国最大色成免费网站 | 欧美成人专区 | 国产成人免费永久播放视频平台 | 男人的天堂免费 | 国产在线一区二区三区四区 | 真正免费一级毛片在线播放 | 精品精品国产高清a毛片 | 国产精品免费视频能看 | 国产亚洲一区二区在线观看 | freexxxx性特大另类ww | 美女视频黄视大全视频免费网址 | 亚洲精品xxx | 亚洲天堂视频在线观看免费 | 国产一区二区免费在线 | 欧美激情免费a视频 | 深夜国产成人福利在线观看女同 | 日本特黄a级高清免费酷网 日本特黄特色 | 日韩精品亚洲一级在线观看 | 精品国产三级a | 欧美午夜视频一区二区三区 | vvvv99日韩精品亚洲 | 中国性孕妇孕交在线 | 成人网免费看 | 免费观看日本视频 | 91久久色 | 国产91无套剧情在线播放 | 色综合九九 | 夜夜操夜夜爽 | 极品美女户外勾搭无套 | 131的美女午夜爱爱爽爽视频 | 黄色影视频 | 国产在线精品香蕉综合网一区 | 国内精品91久久久久 | 波多野结衣一区在线 | 亚洲视频国产视频 | 日本aaa成人毛片 | 欧美一级毛片免费高清aa |