我正在开发嵌入式Linux系统(kernel-5.10.186),我想调试程序中的内存泄漏。
通过pmap -x PID
,我发现进程的堆不断增加。
为了弄清楚增量来自哪里,我在内核 mm/mmap.c 中添加了以下代码,
--- a/kernel/kernel-5.10/mm/mmap.c
+++ b/kernel/kernel-5.10/mm/mmap.c
@@ -269,6 +269,12 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
goto out;
mm->brk = brk;
+ if (strstr(current->comm, "testprog")) {
+ printk("XXXXXX mm->start_brk: %lx, mm->brk: %lx\n", mm->start_brk, mm->brk);
+ if (mm->brk - mm->start_brk >= 0xd0000) {
+ send_sig(SIGSEGV, current, 0);
+ }
+ }
因此,当堆大小超过 0xd0000 时,我会发送 SIGSEGV 来testprog
获取其核心转储,然后gdb
分析回溯以找出增量来自何处。
它成功地生成了核心,但是gdb testprog core
,我只得到了部分回溯,
(gdb) bt
#0 0x77de1994 in brk () from /lib/libc.so.6
#1 0x77de1a88 in sbrk () from /lib/libc.so.6
Backtrace stopped: frame did not save the PC
它没有显示在哪里/谁打电话sbrk()/brk()
。
然后我尝试testprog
使用gdb运行,希望能够捕获现场的回溯,但我仍然未能做到这一点。
这是用于测试的 testprog.c 的演示代码(核心没有显示完整的回溯)。
#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
int main()
{
char *p;
p = malloc(0x2410);
if(p == NULL)
{
printf("malloc error!");
return 0;
}
printf("XXXXXXXXXXXX p = %p\n", p);
printf("Press any key to deploy\n");
getchar();
memset(p, 0, 4100);
printf("Will set more\n");
memset(p, 1, 8192);
while(1) {
p = malloc(1000);
printf("ppppp %p\n", p);
usleep(1000);
}
return 0;
}
我不知道如何调试这种内存泄漏(使用 core 和 gdb,都失败了),并且 valgrind 没有捕获真正的泄漏。
有什么办法可以帮助我吗?我有内核源代码,所以我可以修改它以辅助调试。