內存泄漏是在不帶有垃圾回收(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]?=?' 主站蜘蛛池模板: 国产精品久久免费观看 | 亚洲免费小视频 | 伊人短视频 | 欧美日韩国产在线观看一区二区三区 | 手机看片1024精品日韩 | freexxxx性特大另类ww | 手机在线免费毛片 | 亚洲社区在线观看 | 超清波多野结衣精品一区 | 92精品国产成人观看免费 | 国产精品99久久久久久小说 | 一级毛片aaa片免费观看 | 黄色毛片子| 一区二区三区精品国产欧美 | 国产精品久久免费观看 | 精品在线小视频 | 亚洲精品综合一区二区三区在线 | 在线看片日本 | 欧美精品一区二区在线观看播放 | 久久精品视频16 | 亚洲一区二区三区影院 | 成人精品视频一区二区在线 | 欧美一级特黄特黄做受 | 69性欧美高清影院 | 久久成年片色大黄全免费网站 | 美国一级片在线观看 | 亚洲悠悠色综合中文字幕 | 草草视频手机在线观看视频 | 看全黄男人和女人视频 | 日韩中文字幕精品 | 亚州在线播放 | 日韩精品中文字幕一区三区 | 久青草免费在线视频 | 日韩三级视频在线观看 | 久久免费久久 | 免费观看成人www精品视频在线 | 一区二区三区中文国产亚洲 | 欧美亚洲日本国产综合网 | 很黄的网站在线观看 | 精品一区二区三区亚洲 | 免费国产黄网站在线观看视频 |