如果要通过 wrap malloc
定位 C/C++ 的内存泄漏问题,我会按照以下步骤进行:
1. 使用 wrap malloc
wrap malloc
是一个 Linux 平台提供的工具,它可以拦截程序中的内存分配函数,比如 malloc
和 realloc
,来实现内存泄漏的定位。首先需要安装 libwrap0-dev
:
sudo apt-get update
sudo apt-get install libwrap0-dev
在编译程序时,需要将 --wrap=malloc
选项传递给编译器:
gcc -Wl,--wrap=malloc program.c -o program
2. 分析输出
运行程序后,wrap malloc
会在标准输出中输出内存分配的信息。我们可以通过重定向标准输出来保存这些信息:
./program 2>&1 >log.txt
在 log.txt
文件中将会出现所有的 malloc
调用,以及它们的返回值、参数等信息。我们可以通过观察这些信息来判断程序是否存在内存泄漏问题。
示例说明一:内存泄漏定位
下面是一个示例程序 leak.c
,它会导致内存泄漏:
#include <stdio.h>
#include <stdlib.h>
void func(int n)
{
int *p = malloc(n * sizeof(int));
// 手动释放内存的代码被注释掉了
// free(p);
}
int main()
{
func(10);
func(20);
return 0;
}
首先需要编译这个程序并启用 wrap malloc
:
gcc -Wl,--wrap=malloc leak.c -o leak
然后运行程序并重定向输出:
./leak 2>&1 >log.txt
在 log.txt
文件中,可以发现 malloc
函数被调用了两次,但只有一次被 free
函数释放掉了。这说明程序存在内存泄漏。
示例说明二:动态库内存泄漏
在开发动态库时,内存泄漏问题也会经常出现。下面是一个简单示例,它会在动态库中导致内存泄漏:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
static void * (*real_malloc)(size_t size) = NULL;
void * malloc(size_t size)
{
if (real_malloc == NULL) {
real_malloc = dlsym(RTLD_NEXT, "malloc");
}
void *p = real_malloc(size);
return p;
}
void func()
{
malloc(10);
}
int main()
{
void *handle = dlopen("./libtest.so", RTLD_NOW);
if (handle == NULL) {
printf("dlopen failed: %s\n", dlerror());
return -1;
}
void (*test_func)() = dlsym(handle, "test_func");
if (test_func == NULL) {
printf("dlsym failed: %s\n", dlerror());
dlclose(handle);
return -1;
}
test_func();
dlclose(handle);
return 0;
}
在这个程序中,malloc
函数被重写为拦截器函数,并通过 dlsym
函数动态链接到了动态库中。在动态库中调用 malloc
函数后,即使程序退出,内存仍然没有被释放掉,导致内存泄漏。
我们可以通过以下步骤来找到内存泄漏位置:
- 编译程序并启用
wrap malloc
:
gcc -Wl,--wrap=malloc -ldl main.c -o main
gcc -shared test.c -fPIC -o libtest.so
- 运行程序并重定向标准输出:
./main 2>&1 >log.txt
- 在
log.txt
中搜索动态库中的malloc
,找到最后一次被调用的位置:
[Wed Jun 9 12:16:48 2021] malloc(10) = 0x55de3fa1b010
- 查找调用栈:
#0 malloc@plt (size=10)
#1 0x7fb38a4e4d70 in func (/path/to/test.so+0x11d70)
#2 0x55de3fa1a1db in main (/path/to/main+0x1db)
#3 0x7fb389a5c152 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x28152)
#4 0x55de3fa1a06d in _start (/path/to/main+0x6d)
可以看到,最后一次 malloc
调用发生在动态库中的 func
函数中,因此认为内存泄漏问题是由动态库导致的。
这就是如何通过 wrap malloc
定位 C/C++ 的内存泄漏问题的完整攻略和示例说明。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:如何通过wrap malloc定位C/C++的内存泄漏问题 - Python技术站