Valgrind memcheck 工具显示 0 泄漏,尽管可能存在 memleaks

ren*_*ack 3 c valgrind memory-leaks openwrt compiler-optimization

我需要调查我的 C 项目中的内存泄漏。但在此之前,我只是编写了一个示例程序并交叉编译到ARM-v8-a 64bit OpenWRTlinux平台。通过这个程序,我试图理解 Valgrind 泄漏报告。不幸的是,在这次 valgrind 运行中,没有看到任何泄漏,并期望 memcheck 工具报告 50 字节的泄漏摘要。

Valgrind 工具优化:是,-Os(OpenWRT) and -O2(Valgrind Makefile)
二进制优化:未
使用 libc 标准MUSLOpenWRT ARM 64 位

Why valgrind is not able to intercept malloc calls eventhough binary executes malloc calls?

示例代码:

char *ptr = NULL;
printf("Doing memory alloc\n");
ptr = malloc(50);
if (!ptr) {
    printf("Malloc failure\n");
    return -1;
}
printf("Malloc returned : %p\n", (void *)ptr);
memset(ptr, 0, 50);
strcpy(ptr, "Valgrind leak Analysis!!!\n");
printf("%s\n", ptr);
return 0;
Run Code Online (Sandbox Code Playgroud)

Valgrind 输出:

==481==
--481-- Valgrind options:
--481--    --tool=memcheck
--481--    --leak-check=full
--481--    --show-leak-kinds=all
--481--    --track-origins=yes
--481--    --verbose
--481--    --default-suppressions=no
--481-- Contents of /proc/version:
--481--   Linux version 5.4.164 (renv@bbd-svr-ubt20-004) (gcc version 7.5.0 (OpenWrt GCC 7.5.0 r11-afafb2b1c)) #0 SMP PREEMPT Mon Jun 5 15:00:29 2023
--481--
--481-- Arch and hwcaps: ARM64, LittleEndian, baseline
--481-- Page sizes: currently 4096, max supported 65536
--481-- Valgrind library directory: /usr/lib/valgrind
--481-- Reading syms from /home/superadmin/leaks
--481-- Scheduler: using generic scheduler lock implementation.


Doing memory alloc
Malloc returned : 0x40945e0
Valgrind leak Analysis!!!

==481==
==481== HEAP SUMMARY:
==481==     in use at exit: 0 bytes in 0 blocks
==481==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==481==
==481== All heap blocks were freed -- no leaks are possible
==481==
==481== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Run Code Online (Sandbox Code Playgroud)

以下是我的二进制和 valgrind 文件类型信息:

root@Bean10:/home/superadmin# file leaks
leaks: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-aarch64.so.1, with debug_info, not stripped
root@Bean10:/home/superadmin#
root@Bean10:/home/superadmin# file /usr/bin/valgrind
/usr/bin/valgrind: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-aarch64.so.1, no section header
root@Bean10:/home/superadmin#
root@Bean10:/home/superadmin# ls /usr/lib/valgrind/
64bit-core-valgrind-s1.xml         64bit-linux-valgrind-s2.xml        memcheck-arm64-linux
64bit-core-valgrind-s2.xml         64bit-linux.xml                    none-arm64-linux
64bit-core.xml                     default.supp                       vgpreload_core-arm64-linux.so
64bit-linux-valgrind-s1.xml        leaks                              vgpreload_memcheck-arm64-linux.so
root@Bean10:/home/superadmin#
Run Code Online (Sandbox Code Playgroud)

使用的编译命令:

请注意,这是我的项目中使用的交叉工具链编译器。如何检查这是否隐式使用优化标志。

aarch64-openwrt-linux-musl-gcc -g leaks.c
Run Code Online (Sandbox Code Playgroud)

编译器版本详细信息:

aarch64-openwrt-linux-musl-gcc (OpenWrt GCC 7.5.0 r11-afafb2b1c) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Run Code Online (Sandbox Code Playgroud)

来自目标文件的符号信息:
nm 将malloc和其他一些函数显示为未定义的符号。

$ aarch64-openwrt-linux-musl-nm leaks.o
0000000000000000 T main
                 U malloc
                 U memset
                 U printf
                 U puts

$ aarch64-openwrt-linux-musl-strings -a leaks.o
Doing memory alloc
Malloc failure
Malloc returned : %p
Valgrind leak Analysis!!!
GCC: (OpenWrt GCC 7.5.0 r11-afafb2b1c) 7.5.0
leaks.c
main
puts
malloc
printf
memset
.symtab
.strtab
.shstrtab
.rela.text
.data
.bss
.rodata
.comment
.note.GNU-stack
$
Run Code Online (Sandbox Code Playgroud)

具有文本和 PLT 部分的 objdump 输出:

$ aarch64-openwrt-linux-musl-objdump -D leaks
Run Code Online (Sandbox Code Playgroud)

.plt 节的反汇编:

.....
0000000000400530 <malloc@plt>:
  400530:   b0000090    adrp    x16, 411000 <printf>
  400534:   f9400a11    ldr x17, [x16, #16]
  400538:   91004210    add x16, x16, #0x10
  40053c:   d61f0220    br  x17

0000000000400540 <memset@plt>:
  400540:   b0000090    adrp    x16, 411000 <printf>
  400544:   f9400e11    ldr x17, [x16, #24]
  400548:   91006210    add x16, x16, #0x18
  40054c:   d61f0220    br  x17
Run Code Online (Sandbox Code Playgroud)

.text 节的反汇编:

......
000000000040060c <main>:
  40060c:   a9be7bfd    stp x29, x30, [sp, #-32]!
  400610:   910003fd    mov x29, sp
  400614:   f9000fbf    str xzr, [x29, #24]
  400618:   90000000    adrp    x0, 400000 <_init-0x4d8>
  40061c:   911b0000    add x0, x0, #0x6c0
  400620:   97ffffc0    bl  400520 <puts@plt>
  400624:   d2800640    mov x0, #0x32                   // #50
  400628:   97ffffc2    bl  400530 <malloc@plt>
  40062c:   f9000fa0    str x0, [x29, #24]
  400630:   f9400fa0    ldr x0, [x29, #24]
  400634:   f100001f    cmp x0, #0x0
  400638:   540000c1    b.ne    400650 <main+0x44>  // b.any
  40063c:   90000000    adrp    x0, 400000 <_init-0x4d8>
  400640:   911b6000    add x0, x0, #0x6d8
  400644:   97ffffb7    bl  400520 <puts@plt>
  400648:   12800000    mov w0, #0xffffffff             // #-1
  40064c:   14000016    b   4006a4 <main+0x98>
  400650:   90000000    adrp    x0, 400000 <_init-0x4d8>
  400654:   911ba000    add x0, x0, #0x6e8
  400658:   f9400fa1    ldr x1, [x29, #24]
  40065c:   97ffffad    bl  400510 <printf@plt>
  400660:   d2800642    mov x2, #0x32                   // #50
  400664:   52800001    mov w1, #0x0                    // #0
  400668:   f9400fa0    ldr x0, [x29, #24]
  40066c:   97ffffb5    bl  400540 <memset@plt>
  400670:   f9400fa2    ldr x2, [x29, #24]
  400674:   90000000    adrp    x0, 400000 <_init-0x4d8>
  400678:   911c0001    add x1, x0, #0x700
  40067c:   aa0203e0    mov x0, x2
  400680:   a9400c22    ldp x2, x3, [x1]
  400684:   a9000c02    stp x2, x3, [x0]
  400688:   f9400822    ldr x2, [x1, #16]
  40068c:   f9000802    str x2, [x0, #16]
  400690:   b8417021    ldur    w1, [x1, #23]
  400694:   b8017001    stur    w1, [x0, #23]
  400698:   f9400fa0    ldr x0, [x29, #24]
  40069c:   97ffffa1    bl  400520 <puts@plt>
  4006a0:   52800000    mov w0, #0x0                    // #0
  4006a4:   a8c27bfd    ldp x29, x30, [sp], #32
  4006a8:   d65f03c0    ret
Run Code Online (Sandbox Code Playgroud)

Valgrind 如何编译
Valgrind 使用以下优化和强化选项构建。

-O2 -g -Wall -Wmissing-prototypes -Wshadow -Wpointer-arith -Wstrict-prototypes -Wmissing-declarations -Wcast-align -Wcast-qual -Wwrite-strings -Wempty-body -Wformat -Wformat-signedness -Wformat-security -Wignored-qualifiers -Wmissing-parameter-type -Wlogical-op -Wimplicit-fallthrough=2 -Wold-style-declaration -finline-functions -fno-stack-protector -fno-strict-aliasing -fno-builtin  -O2 -Os -pipe -march=armv8-a -mcpu=cortex-a73+crypto -fno-caller-saves -fno-plt -Wa,--noexecstack -fhonour-copts -Wno-error=unused-but-set-variable -Wno-error=unused-result -iremap/home/renv/BBD_R2302OpenWrtB/working/QSDK12/qsdk/build_dir/target-aarch64/valgrind-3.15.0:valgrind-3.15.0 -Wformat -Werror=format-security -fPIC -D_FORTIFY_SOURCE=2 -Wl,-z,now -Wl,-z,relro
Run Code Online (Sandbox Code Playgroud)

期待一些帮助/指示以进一步进行。

Cai*_*ner 5

由于从未使用过您的变量,因此很可能会malloc通过优化将其删除。ptr

这是 ARM64 gcc 13.1 (linux) 在给出优化标志时生成的程序集-O3。如您所见,malloc呼叫已被删除。

.LC0:
        .string "Doing memory alloc"
main:
        stp     x29, x30, [sp, -16]!
        adrp    x0, .LC0
        add     x0, x0, :lo12:.LC0
        mov     x29, sp
        bl      puts
        mov     w0, 0
        ldp     x29, x30, [sp], 16
        ret
Run Code Online (Sandbox Code Playgroud)

更新

OP 提供了二进制文件的反汇编,其中显示了对 的调用malloc(50),表明该程序实际上是在没有优化的情况下编译的,并且 OP 很可能已经发现了 valgrind 中的错误。我留下我的答案供参考,以防将来有人遇到类似的问题,而罪魁祸首是编译器优化。

  • @renga_in_stack,感谢您提供二进制文件的程序集。事实上,程序集显示了对“malloc(50)”的调用。这表明该程序实际上确实调用了 malloc,并且无论出于何种原因,valgrind 都没有报告内存泄漏。 (3认同)