如何確定有內存泄露問題,如何定位到內存泄露位置,如何寫一個內存泄漏檢測工具?
1:概述
內存泄露本質:其實就是申請調用malloc/new,但是釋放調用free/delete有遺漏,或者重復釋放的問題。
內存泄露會導致的現象:作為一個服務器,長時間運行,內存泄露會導致進程虛擬內存被占用完,導致進程崩潰吧。(堆上分配的內存)
如何規避或者發現內存泄露呢?
===》1:如何檢測有內存泄露?(除了內存監控工具htop,耗時,效果不明顯)
===》2:如何定位內存泄露的代碼問題(少量代碼可以閱讀代碼排除,線上版本呢?)
=====》引入gc
=====》少量代碼可以通過排查代碼進行定位
=====》已經確定代碼有內存泄露,可以用過valgrind/mtrace等市場上已有的一些工具
=====》本質是malloc和free的次數不一致導致,我們通過hook的方式,對malloc和free次數進行統計
2:通過hook的方式檢測,定位內存泄露(四種方法)
在生產環境重定位內存泄露的問題,我們可以在產品中增加這些定位手段,通過配置文件開關控制其打開,方便內存泄露定位。
幾種不同的方式本質:都是對malloc和free進行hook,增加一些處理進行檢測。
2.1:測試代碼描述內存泄露
如下代碼,從代碼看,明顯可以看到是有內存泄露的,但是如果看不到代碼,或者代碼量過多,從運行現象上我們就很難發現了。
#include < stdio.h >
#include < stdlib.h >
int main()
{
void * ptr1 = malloc(10);
void * ptr2 = malloc(20);
free(ptr1);
void * ptr3 = malloc(30);
free(ptr3);
return 0;
}
//代碼運行是沒有問題,也沒有報錯的,但是明顯可以看到ptr2是沒有內存釋放的,如果是服務器有這種代碼,長時間運行會有嚴重問題的。
2.2:通過dlsym庫函數對malloc/free進行hook
我在 Linux/unix系統編程手冊 這本書中了解相關dlsym函數的使用
要想知道有內存泄露,或者直接定位內存泄露的代碼位置,本質還是對調用的malloc/free進行hook, 對調用malloc/free分別增加監控來分析。
使用dlsym庫函數,獲取malloc/free函數的地址,通過RTLD_NEXT進行比標記(這個標記適用于在其他地方定義的函數同名的包裝函數,如在主程序中定義的malloc,代替系統的malloc),實現用我們主程序中malloc代替系統調用malloc.
2.2.1:第一版試著
在調用malloc和free前,使用dlsym函數和RTLD_NEXT標記,獲取系統庫malloc/free地址,以及用本地定義的malloc/free代替系統調用。
//1:使用void * dlsym(void* handle, char* symbool)函數和handle為RTLD_NEXT標記,對malloc/free進行hook
//2:RTLD_NEXT標記 需要在本地實現 symbool同名函數達到hook功能,即這里要實現malloc/free功能
//3:dlsym()返回的是symbool 參數對應的函數的地址,在同名函數中用該地址實現真正的調用
//RTLD_NEXT 是dlsym() 庫中的偽句柄,定義_GNU_SOURCE宏才能識別
//可以通過 man dlsym
//測試發現 :必須放在最頂部,不然編譯報 RTLD_NEXT沒有定義
#define _GNU_SOURCE
#include < dlfcn.h > //對應的頭文件
//第一步功能,確定hook成功,先在我們的hook函數中增加一些打印信息驗證
#include < stdio.h >
#include < stdlib.h >
//定義相關全局變量,獲取返回的函數地址,進行實際調用
typedef void *(*malloc_t)(size_t size);
malloc_t malloc_f = NULL;
typedef void (*free_t)(void* p);
free_t free_f = NULL;
//要hook的同名函數
void * malloc(size_t size){
printf("exec malloc n");
return malloc_f(size);
}
void free(void * p){
printf("exec free n");
free_f(p);
}
//通過dlsym 對malloc和free使用前進行hook
static void init_malloc_free_hook(){
//只需要執行一次
if(malloc_f == NULL){
malloc_f = dlsym(RTLD_NEXT, "malloc"); //除了RTLD_NEXT 還有一個參數RTLD_DEFAULT
}
if(free_f == NULL)
{
free_f = dlsym(RTLD_NEXT, "free");
}
return ;
}
int main()
{
init_malloc_free_hook(); //執行一次
void * ptr1 = malloc(10);
void * ptr2 = malloc(20);
free(ptr1);
void * ptr3 = malloc(30);
free(ptr3);
return 0;
}
上述代碼是有問題的,現象及定位問題:
hlp@ubuntu:~/mem_test$ gcc dlsym_hook.c -o dlsym_hook -ldl
hlp@ubuntu:~/mem_test$ ./dlsym_hook
Segmentation fault (core dumped)
#使用gdb對問題進行定位
hlp@ubuntu:~/mem_test$ gdb ./dlsym_hook
(gdb) b 54 #加斷點
Breakpoint 1 at 0x400729: file dlsym_hook.c, line 54.
(gdb) b 28 #加斷點
Breakpoint 2 at 0x400682: file dlsym_hook.c, line 28.
(gdb) r #開始運行
Starting program: /home/hlp/mem_test/dlsym_hook
Breakpoint 1, main () at dlsym_hook.c:54
54 void * ptr1 = malloc(10);
(gdb) c #單步執行
Continuing.
Breakpoint 2, malloc (size=10) at dlsym_hook.c:28 #第一個mallocy已經執行
28 printf("exec malloc n");
(gdb) c
Continuing.
Breakpoint 2, malloc (size=1024) at dlsym_hook.c:28 #這里的1024不是我們代碼里面的,
28 printf("exec malloc n");
(gdb) c
Continuing.
Breakpoint 2, malloc (size=1024) at dlsym_hook.c:28 #發現malloc 1024一直循環執行 懷疑是printf中會調用malloc,
28 printf("exec malloc n");
(gdb) c
Continuing.
Breakpoint 2, malloc (size=1024) at dlsym_hook.c:28
28 printf("exec malloc n");
(gdb)
#通過gdb進行定位時,可以確定,我們hook malloc函數內部調用printf,printf底層其實是有調用malloc,從而printf內部成為遞歸,一直調用了。
#所以我們需要規避這種現象,讓hook函數內部其他業務只執行一次,不要因為第三方庫內部機制導致類似問題
增加特定標識,優化上述代碼:
//使用標識,使hook的函數內部只執行一次,不因為第三方庫原因導致遞歸現象
#define _GNU_SOURCE
#include < dlfcn.h > //對應的頭文件
#include < stdio.h >
#include < stdlib.h >
typedef void *(*malloc_t)(size_t size);
malloc_t malloc_f = NULL;
typedef void (*free_t)(void* p);
free_t free_f = NULL;
//定義一個hook函數的標志 使內部邏輯只執行一次
int enable_malloc_hook = 1;
int enable_free_hook = 1;
//要hook的同名函數
void * malloc(size_t size){
if(enable_malloc_hook) //對第三方調用導致的遞歸進行規避
{
enable_malloc_hook = 0;
printf("exec malloc n");
enable_malloc_hook = 1;
}
return malloc_f(size);
}
void free(void * p){
if(enable_free_hook){
enable_free_hook = 0;
printf("exec free n");
enable_free_hook = 1;
}
free_f(p);
}
//通過dlsym 對malloc和free使用前進行hook
static void init_malloc_free_hook(){
//只需要執行一次
if(malloc_f == NULL){
malloc_f = dlsym(RTLD_NEXT, "malloc"); //除了RTLD_NEXT 還有一個參數RTLD_DEFAULT
}
if(free_f == NULL)
{
free_f = dlsym(RTLD_NEXT, "free");
}
return ;
}
int main()
{
init_malloc_free_hook(); //執行一次
void * ptr1 = malloc(10);
void * ptr2 = malloc(20);
free(ptr1);
void * ptr3 = malloc(30);
free(ptr3);
return 0;
}
上述代碼執行成功,現象如下:
hlp@ubuntu:~/mem_test$ gcc dlsym_hook_ok.c -o dlsym_hook_ok -ldl -g
hlp@ubuntu:~/mem_test$ ./dlsym_hook_ok
exec malloc
exec malloc
exec free
exec malloc
exec free
#對比執行的 malloc和free次數 可以確定有內存泄露
如何增加行號標識呢?讓我們確定到代碼位置?
如何確定有內存泄露呢?直接通過代碼,識別到malloc/free的對應次數,定位到有代碼問題的位置。
2.2.2:能識別到行號,以及有問題代碼位置
//我們知道,一般可以通過__LINE__ 標識日志當前行號位置,但是這里不適用
//可以通過 __builtin_return_address 獲取上級調用的退出的地址,可以設置時1級,也可以設置是2級別...
// 增加打印調用malloc和free位置的信息。 這里打印地址 通過addr2line進行地址和行號轉換
#define _GNU_SOURCE
#include < dlfcn.h > //對應的頭文件
#include < stdio.h >
#include < stdlib.h >
typedef void *(*malloc_t)(size_t size);
malloc_t malloc_f = NULL;
typedef void (*free_t)(void* p);
free_t free_f = NULL;
int enable_malloc_hook = 1;
int enable_free_hook = 1;
void * malloc(size_t size){
if(enable_malloc_hook) //對第三方調用導致的遞歸進行規避
{
enable_malloc_hook = 0;
//打印上層調用的地址
void *carrer = __builtin_return_address(0);
printf("exec malloc [%p ]n", carrer );
enable_malloc_hook = 1;
}
return malloc_f(size);
}
void free(void * p){
if(enable_free_hook){
enable_free_hook = 0;
void *carrer = __builtin_return_address(0);
printf("exec free [%p]n", carrer);
enable_free_hook = 1;
}
free_f(p);
}
//通過dlsym 對malloc和free使用前進行hook
static void init_malloc_free_hook(){
//只需要執行一次
if(malloc_f == NULL){
malloc_f = dlsym(RTLD_NEXT, "malloc"); //除了RTLD_NEXT 還有一個參數RTLD_DEFAULT
}
if(free_f == NULL)
{
free_f = dlsym(RTLD_NEXT, "free");
}
return ;
}
int main()
{
init_malloc_free_hook(); //執行一次
void * ptr1 = malloc(10);
void * ptr2 = malloc(20);
free(ptr1);
void * ptr3 = malloc(30);
free(ptr3);
return 0;
}
執行結果及查找對應行數:
#執行結果如下
hlp@ubuntu:~/mem_test$ gcc dlsym_hook_addr.c -o dlsym_hook_addr -ldl
hlp@ubuntu:~/mem_test$ ./dlsym_hook_addr
exec malloc [0x400797 ]
exec malloc [0x4007a5 ]
exec free [0x4007b5]
exec malloc [0x4007bf ]
exec free [0x4007cf]
#可以通過addr2line 獲取到對應的代碼行數 編譯的時候要帶 -g
hlp@ubuntu:~/mem_test$ addr2line -fe ./dlsym_hook_addr -a 0x400797
0x0000000000400797
main
/home/hlp/mem_test/dlsym_hook_addr.c:57
2.2.3:通過策略,查找有問題的代碼
從上文可以知道,我們通過對malloc和free的hook,可以獲得各自malloc和hook的次數。
以及我們可以通過__builtin_return_address 接口獲取到實際調用malloc/free的位置。
除此之外,malloc之間有所關聯的是申請內存的地址,
匯總:
===》可以思考,通過malloc和free關聯的地址作為標識,對malloc和free的次數進行統計即可。
===》可以設計數據結構,對不同地址,malloc的地址和free的地址進行保存,malloc的次數和free的次數進行控制判斷
===》這里根據老師的邏輯,用文件的方式進行控制。
測試代碼如下:
// malloc和free 之間的關聯是申請內存的地址,以該地址作為基準
// malloc時寫入一個文件,打印行數等必要信息 free時刪除這個文件 通過有剩余文件判斷內存泄露
#define _GNU_SOURCE
#include < dlfcn.h > //對應的頭文件
#include < stdio.h >
#include < stdlib.h >
#include < unistd.h >
typedef void *(*malloc_t)(size_t size);
malloc_t malloc_f = NULL;
typedef void (*free_t)(void* p);
free_t free_f = NULL;
int enable_malloc_hook = 1;
int enable_free_hook = 1;
#define MEM_FILE_LENGTH 40
void * malloc(size_t size){
if(enable_malloc_hook) //對第三方調用導致的遞歸進行規避
{
enable_malloc_hook = 0;
//實際的內存申請,根據該地址寫文件和free 相互關聯
void *ptr =malloc_f(size);
//打印上層調用的地址
void *carrer = __builtin_return_address(0);
printf("exec malloc [%p ]n", carrer );
//通過寫入文件的方式 對malloc和free進行關聯 malloc時寫入文件
char file_buff[MEM_FILE_LENGTH] = {0};
sprintf(file_buff, "./mem/%p.mem", ptr);
//打開文件寫入必要信息 使用前創建目錄級別
FILE *fp = fopen(file_buff, "w");
fprintf(fp, "[malloc addr : +%p ] ---- >mem:%p size:%lu n",carrer, ptr, size);
fflush(fp); //刷新寫入文件
enable_malloc_hook = 1;
return ptr;
}else
{
return malloc_f(size);
}
}
void free(void * p){
if(enable_free_hook){
enable_free_hook = 0;
void *carrer = __builtin_return_address(0);
//free時刪除文件 根據剩余文件判斷內存泄露
char file_buff[MEM_FILE_LENGTH] = {0};
sprintf(file_buff, "./mem/%p.mem", p);
//刪除文件 根據malloc對應的指針
if(unlink(file_buff) < 0)
{
printf("double free: %p, %p n", p, carrer);
}
//這里的打印實際就沒意義了
printf("exec free [%p]n", carrer);
free_f(p);
enable_free_hook = 1;
}else
{
free_f(p);
}
}
//通過dlsym 對malloc和free使用前進行hook
static void init_malloc_free_hook(){
//只需要執行一次
if(malloc_f == NULL){
malloc_f = dlsym(RTLD_NEXT, "malloc"); //除了RTLD_NEXT 還有一個參數RTLD_DEFAULT
}
if(free_f == NULL)
{
free_f = dlsym(RTLD_NEXT, "free");
}
return ;
}
int main()
{
init_malloc_free_hook(); //執行一次
void * ptr1 = malloc(10);
void * ptr2 = malloc(20);
free(ptr1);
void * ptr3 = malloc(30);
free(ptr3);
return 0;
}
執行結果:
# 這里的打印只是為了理解 沒有多大意義,真正的分析還得依靠文件目錄
hlp@ubuntu:~/mem_test$ mkdir mem
hlp@ubuntu:~/mem_test$ gcc dlsym_hook_file.c -o dlsym_hook_file -ldl -g
hlp@ubuntu:~/mem_test$ ./dlsym_hook_file
exec malloc [0x400ad5 ]
exec malloc [0x400ae3 ]
exec free [0x400af3]
exec malloc [0x400afd ]
exec free [0x400b0d]
hlp@ubuntu:~/mem_test$ cd mem/
# 這里在我們的目標目錄下 看到有文件存在,說明存在內存泄露
hlp@ubuntu:~/mem_test/mem$ ls
0xe38680.mem
# 通過文件中的日志信息,對其進行分析,找到問題代碼位置
hlp@ubuntu:~/mem_test/mem$ cat 0xe38680.mem
[malloc addr : +0x400ae3 ] ---- >mem:0xe38680 size:20
hlp@ubuntu:~/mem_test/mem$ cd ../
#通過地址轉換 找到我們有問題代碼 沒有釋放的代碼位置
hlp@ubuntu:~/mem_test$ addr2line -fe ./dlsym_hook_file 0x400ae3
main
/home/hlp/mem_test/dlsym_hook_file.c:85
2.3:通過宏定義的方式對malloc/free進行hook
本質其實就是對系統調用的malloc/free進行替換,調用我們的目標方法,可以通過hook或者重載的方法實現。
使用宏定義的方式,實現malloc/free的替換。
#include < stdio.h >
#include < stdlib.h >
//不能放在這里 放在這里 會對malloc_hook 和 free_hook 內部實際調用的也替換,就形成的遞歸調用了 并且無法規避
//#define malloc(size) malloc_hook(size, __FILE__, __LINE__)
//#define free(p) free_hook(p, __FILE__, __LINE__)
#define MEM_FILE_LENGTH 40
//實現目標函數
void *malloc_hook(size_t size, const char* file, int line)
{
//這里還是通過文件的方式進行識別
void *ptr =malloc(size);
char file_name_buff[MEM_FILE_LENGTH] = {0};
sprintf(file_name_buff, "./mem/%p.mem", ptr);
//打開文件寫入必要信息 使用前創建目錄級別
FILE *fp = fopen(file_name_buff, "w");
fprintf(fp, "[file:%s line:%d ] ---- >mem:%p size:%lu n",file, line, ptr, size);
fflush(fp); //刷新寫入文件
printf("exec malloc [%p:%lu], file: %s, line:%d n", ptr, size, file, line );
return ptr;
}
void free_hook(void *p, const char* file, int line)
{
char file_name_buff[MEM_FILE_LENGTH] = {0};
sprintf(file_name_buff, "./mem/%p.mem", p);
if(unlink(file_name_buff) < 0)
{
printf("double free: %p, file: %s. line :%d n", p, file, line);
}
//這里的打印實際就沒意義了
printf("exec free [%p], file: %s line:%d n", p, file, line);
free(p);
}
//宏定義實現代碼中調用malloc/free時調用我們目標函數
#define malloc(size) malloc_hook(size, __FILE__, __LINE__)
#define free(p) free_hook(p, __FILE__, __LINE__)
int main()
{
//init_malloc_free_hook(); //執行一次
void * ptr1 = malloc(10);
void * ptr2 = malloc(20);
free(ptr1);
void * ptr3 = malloc(30);
free(ptr3);
return 0;
}
代碼執行如下:
hlp@ubuntu:~/mem_test$ gcc define_hook.c -o define_hook
hlp@ubuntu:~/mem_test$ ./define_hook
exec malloc [0x1f91010:10], file: define_hook.c, line:47
exec malloc [0x1f92680:20], file: define_hook.c, line:48
exec free [0x1f91010], file: define_hook.c line:50
exec malloc [0x1f938e0:30], file: define_hook.c, line:52
exec free [0x1f938e0], file: define_hook.c line:53
#通過目錄下文件 以及文件內容 可以分析到代碼有問題的行號
#注意 測試前最好清空目錄下的文件
hlp@ubuntu:~/mem_test$ ls ./mem
0x1f92680.mem
hlp@ubuntu:~/mem_test$ cat ./mem/0x1f92680.mem
[file:define_hook.c line:48 ] ---- >mem:0x1f92680 size:20
2.4:_libc_malloc
對malloc進行劫持 使用實際的內存申請_libc_malloc 進行申請內存以及其他控制
#include < stdio.h >
#include < stdlib.h >
#include < unistd.h >
//實際內存申請的函數
extern void *__libc_malloc(size_t size);
int enable_malloc_hook = 1;
extern void __libc_free(void* p);
int enable_free_hook = 1;
// func -- > malloc() { __builtin_return_address(0)}
// callback -- > func -- > malloc() { __builtin_return_address(1)}
// main -- > callback -- > func -- > malloc() { __builtin_return_address(2)}
//calloc, realloc
void *malloc(size_t size) {
if (enable_malloc_hook) {
enable_malloc_hook = 0;
void *p = __libc_malloc(size); //重載達到劫持后 實際內存申請
void *caller = __builtin_return_address(0); // 0
char buff[128] = {0};
sprintf(buff, "./mem/%p.mem", p);
FILE *fp = fopen(buff, "w");
fprintf(fp, "[+%p] -- > addr:%p, size:%ldn", caller, p, size);
fflush(fp);
//fclose(fp); //free
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) < 0) { // no exist
printf("double free: %pn", p);
}
__libc_free(p);
// rm -rf p.mem
enable_free_hook = 1;
} else {
__libc_free(p);
}
}
int main()
{
//init_malloc_free_hook(); //執行一次
void * ptr1 = malloc(10);
void * ptr2 = malloc(20);
free(ptr1);
void * ptr3 = malloc(30);
free(ptr3);
return 0;
}
代碼運行及分析如下:
hlp@ubuntu:~/mem_test$ gcc libc_hook.c -o libc_hook -g
hlp@ubuntu:~/mem_test$ ./libc_hook
#通過查看目錄下生成的文件 可以知道有內存泄露 通過日志內部信息 使用addr2line 通過打印地址找到對應的代碼位置
hlp@ubuntu:~/mem_test$ cat ./mem/0x733270.mem
[+0x4009f7] -- > addr:0x733270, size:20
hlp@ubuntu:~/mem_test$ addr2line -fe ./libc_hook 0x4009f7
main
/home/hlp/mem_test/libc_hook.c:69 #找到問題代碼位置
2.5:mem_trace
原理:glic提供__malloc_hook, __realloc_hook, __free_hook可以實現hook自定義malloc/free函數
#include < stdlib.h >
#include < stdio.h >
#include < unistd.h >
#include < malloc.h >
/* #include < malloc.h >
void *(*__malloc_hook)(size_t size, const void *caller);
void *(*__realloc_hook)(void *ptr, size_t size, const void *caller);
void *(*__memalign_hook)(size_t alignment, size_t size,
const void *caller);
void (*__free_hook)(void *ptr, const void *caller);
void (*__malloc_initialize_hook)(void);
void (*__after_morecore_hook)(void);*/
//#include < mcheck.h >
typedef void *(*malloc_hook_t)(size_t size, const void *caller);
typedef void (*free_hook_t)(void *p, const void *caller);
malloc_hook_t old_malloc_f = NULL;
free_hook_t old_free_f = NULL;
int replaced = 0;
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]n", caller, ptr);
char buff[128] = {0};
sprintf(buff, "./mem/%p.mem", ptr);
FILE *fp = fopen(buff, "w");
fprintf(fp, "[+%p] -- > addr:%p, size:%ldn", caller, ptr, size);
fflush(fp);
fclose(fp); //free
mem_trace();
return ptr;
}
void *free_hook_f(void *p, const void *caller) {
mem_untrace();
//printf("-%p: addr[%p]n", caller, p);
char buff[128] = {0};
sprintf(buff, "./mem/%p.mem", p);
if (unlink(buff) < 0) { // no exist
printf("double free: %pn", p);
return NULL;
}
free(p);
mem_trace();
}
//對__malloc_hook 和__free_hook 重賦值
void mem_trace(void) { //mtrace
replaced = 1;
old_malloc_f = __malloc_hook; //malloc -- >
old_free_f = __free_hook;
__malloc_hook = malloc_hook_f;
__free_hook = free_hook_f;
}
//還原 __malloc_hook 和__free_hook
void mem_untrace(void) {
__malloc_hook = old_malloc_f;
__free_hook = old_free_f;
replaced = 0;
}
int main()
{
mem_trace(); //mtrace(); //進行hook劫持
void * ptr1 = malloc(10);
void * ptr2 = malloc(20);
free(ptr1);
void * ptr3 = malloc(30);
free(ptr3);
mem_untrace(); //muntrace(); //取消劫持
return 0;
}
這里編譯的時候有一些警告,但是編譯成功了,
除此之外 相關資料可以用 man __malloc_hook 去了解
hlp@ubuntu:~/mem_test$ gcc 3.c -o 3 -g
hlp@ubuntu:~/mem_test$ ./3
hlp@ubuntu:~/mem_test$ cat mem/0x1789030.mem
[+0x400ab2] -- > addr:0x1789030, size:20
hlp@ubuntu:~/mem_test$ addr2line -fe ./3 0x400ab2
main
#可以確定問題代碼位置
/home/hlp/mem_test/3.c:79
3:總結:
內存泄露的本質是,在堆上分配內存,使用malloc/calloc/realloc 以及內存的釋放free不匹配導致的。
怎么檢測,定位內存泄露?:
===》實際上對內存管理的相關函數進行劫持(hook),增加一些必要信息供我們分析。
===》不同的方案,其實就是劫持(hook的方式不一樣)
===》可以使用重載,宏定義,操作系統提供的hook方式(__malloc_hook)等不通的方案
===》在hook的基礎上,要進行分析,需要用相關的策略,這里用的多個文件,可以用數據結構管理。
===》除此之外,__builtin_return_address函數可以獲取函數調用地址,以及addr2line命令對地址和代碼行數進行轉換,確定問題代碼位置。
===》編譯的時候,要加-g,addr2line才可用。
這里只是簡單的內存泄露hook的一些方案demo,有關多線程等細節再實際項目中也需要考慮。
-
服務器
+關注
關注
12文章
9029瀏覽量
85207 -
Free
+關注
關注
0文章
16瀏覽量
11077 -
內存泄漏
+關注
關注
0文章
39瀏覽量
9206 -
虛擬內存
+關注
關注
0文章
70瀏覽量
8052
發布評論請先 登錄
相關推薦
評論