私は組み込み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()
。
その後、リアルタイムのバックトレースをキャプチャするためにgdbで実行しようとしましたが、testprog
それでも失敗しました。
これはテストに使用された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は実際のリークをキャッチしません。
私を助ける方法はありますか?カーネルのソースコードがあるので、デバッグを助けるために変更することができます。