MIPS上的Valgrind报告没有堆使用情况

Woo*_*low 20 c valgrind memory-leaks memory-management mips

我正在使用valgrind(v3.10.0)来寻找复杂应用程序(一个经过大量修改的net-snmp版本)中的内存泄漏,该应用程序是作为更大的软件套件的一部分构建的.我确信存在泄漏(应用程序的内存占用量无限制地线性增长),但valgrind总是在终止时报告以下内容.

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

总堆的使用不能为零-还有很多,很多电话mallocfree整个应用程序.Valgrind仍然能够找到"无效写入"错误.

正在编译该应用程序以及其他软件包,其中MIPS处理器的uclibc-gcc工具链(uclibc v0.9.29)将被闪存到运行busybox(v1.17.2)linux shell的嵌入式设备上.我正在设备上直接运行valgrind.我在启动Valgrind时使用以下选项:

--tool=memcheck --leak-check=full --undef-value-errors=no --trace-children=yes
Run Code Online (Sandbox Code Playgroud)

基本上,即使我使用了堆,Valgrind也没有检测到任何堆使用情况.为什么会这样?我的任何假设(下面)都是错误的吗?


我试过的

简单的测试程序

我从Valgrind 快速入门教程编译了简单的测试程序(使用与上面的应用程序相同的目标和工具链),以查看Valgrind是否会检测到泄漏.最终输出与上面相同:没有堆使用.

链接问题?

Valgrind文档在他们的FAQ上有如下说明:

如果您的程序是静态链接的,那么大多数Valgrind工具只有在能够用自己的版本替换某些功能(例如malloc)时才能正常工作.默认情况下,不替换静态链接的malloc函数.一个关键的指标是,如果Memcheck说"所有堆块都被释放 - 没有泄漏是可能的".

上面的声音与我的问题完全一样,所以我检查它是否动态链接到包含malloc和的C库free.我使用了uclibc工具链的自定义ldd可执行文件(我不能使用原生linuxldd),输出包括以下几行:

libc.so.0 => not found (0x00000000)
/lib/ld-uClibc.so.0 => /lib/ld-uClibc.so.0 (0x00000000)
Run Code Online (Sandbox Code Playgroud)

(找不到它们的原因是因为我在x86主机设备上运行它; mips目标设备没有ldd可执行文件.)根据我的理解,malloc并且free将在其中一个库中,并且它们似乎是动态链接的.我也没有readelfnm对可执行文件,以确认该引用mallocfree是不确定的(这是一个动态链接的可执行文件的特性).

此外,我尝试--soname-synonyms=somalloc=NONE按照FAQ的建议启动Valgrind .

LD_PRELOAD支持?

正如评论者和回答者所指出的,Valgrind依赖于LD_PRELOAD的使用.有人建议我的工具链不支持此功能.为了确认它,我按照这个例子创建了一个简单的测试库并加载它(我rand()用一个只返回42的函数替换).测试工作,所以看起来我的目标支持LD_PRELOAD就好了.

精灵数据

我还将从readelf命令中包含一些可能有用的信息.而不是一个巨大的转储,我已经削减了一些东西,只包括可能相关的东西.

Dynamic section
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libnetsnmpagent.so.30]
 0x00000001 (NEEDED)                     Shared library: [libnetsnmpmibs.so.30]
 0x00000001 (NEEDED)                     Shared library: [libnetsnmp.so.30]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libc.so.0]
 0x0000000f (RPATH)                      Library rpath: [//lib]

Symbol table '.dynsym'
   Num:    Value  Size Type    Bind   Vis      Ndx Name
    27: 00404a40     0 FUNC    GLOBAL DEFAULT  UND free
    97: 00404690     0 FUNC    GLOBAL DEFAULT  UND malloc
Run Code Online (Sandbox Code Playgroud)

abl*_*igh 10

首先,让我们做一个真正的测试,看看是否有静态链接.

$ ldd -v /bin/true
    linux-vdso.so.1 =>  (0x00007fffdc502000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0731e11000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f07321ec000)

    Version information:
    /bin/true:
        libc.so.6 (GLIBC_2.3) => /lib/x86_64-linux-gnu/libc.so.6
        libc.so.6 (GLIBC_2.3.4) => /lib/x86_64-linux-gnu/libc.so.6
        libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6
        libc.so.6 (GLIBC_2.4) => /lib/x86_64-linux-gnu/libc.so.6
        libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6
    /lib/x86_64-linux-gnu/libc.so.6:
        ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2
        ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2
Run Code Online (Sandbox Code Playgroud)

输出中的第二行显示它是动态链接到的libc,它包含的内容malloc.

至于可能出现的问题,我可以建议四件事:

  1. 也许它与正常情况无关libc,但与某些其他C库(例如uclibc)或其他东西valgrind没有预料到.上述测试将准确显示与之相关的内容.为了valgrind工作,它用于LD_PRELOAD包装malloc()free()函数(这里包含一般函数的描述).如果您的libc替代品不支持LD_PRELOAD或(某种方式)C库malloc()并且free()根本没有使用(使用这些名称),那么valgrind就不会起作用.也许您可以包含构建应用程序时使用的链接行.

  2. 它正在泄漏,但它没有使用分配内存malloc().例如,它可能(不太可能)进行自己的调用brk(),或者(更有可能)分配内存mmap.你可以用它来找出(这是一个cat自己的转储).

.

$ cat /proc/PIDNUMBERHERE/maps
00400000-0040b000 r-xp 00000000 08:01 805303                             /bin/cat
0060a000-0060b000 r--p 0000a000 08:01 805303                             /bin/cat
0060b000-0060c000 rw-p 0000b000 08:01 805303                             /bin/cat
02039000-0205a000 rw-p 00000000 00:00 0                                  [heap]
7fbc8f418000-7fbc8f6e4000 r--p 00000000 08:01 1179774                    /usr/lib/locale/locale-archive
7fbc8f6e4000-7fbc8f899000 r-xp 00000000 08:01 1573024                    /lib/x86_64-linux-gnu/libc-2.15.so
7fbc8f899000-7fbc8fa98000 ---p 001b5000 08:01 1573024                    /lib/x86_64-linux-gnu/libc-2.15.so
7fbc8fa98000-7fbc8fa9c000 r--p 001b4000 08:01 1573024                    /lib/x86_64-linux-gnu/libc-2.15.so
7fbc8fa9c000-7fbc8fa9e000 rw-p 001b8000 08:01 1573024                    /lib/x86_64-linux-gnu/libc-2.15.so
7fbc8fa9e000-7fbc8faa3000 rw-p 00000000 00:00 0
7fbc8faa3000-7fbc8fac5000 r-xp 00000000 08:01 1594541                    /lib/x86_64-linux-gnu/ld-2.15.so
7fbc8fca6000-7fbc8fca9000 rw-p 00000000 00:00 0
7fbc8fcc3000-7fbc8fcc5000 rw-p 00000000 00:00 0
7fbc8fcc5000-7fbc8fcc6000 r--p 00022000 08:01 1594541                    /lib/x86_64-linux-gnu/ld-2.15.so
7fbc8fcc6000-7fbc8fcc8000 rw-p 00023000 08:01 1594541                    /lib/x86_64-linux-gnu/ld-2.15.so
7fffe1674000-7fffe1695000 rw-p 00000000 00:00 0                          [stack]
7fffe178d000-7fffe178f000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Run Code Online (Sandbox Code Playgroud)

请注意结束地址[heap]是否实际增长,或者您是否看到其他mmap条目.是否valgrind有效的另一个好的指标是发送一个SIGSEGV或类似的进程,看看你是否在退出时看到堆正在使用.

  1. 它不是严格意义上的泄漏,而是泄漏到所有意图和目的.例如,它可能具有数据结构(如缓存),随着时间的推移而增长.退出时,程序(正确)释放缓存中的所有条目.因此,在退出时,堆上没有任何东西在使用.在这种情况下,您将想知道正在发展的是什么.这是一个更难的主张.我将使用该技术杀死程序(上图),捕获输出并对其进行后处理.如果您在24小时后看到500件事,48小时后看到1,000件,在72小时后看到1,500件,这应该可以告诉您什么是"泄漏".但是,正如haris在评论中指出的那样,虽然这会导致内存不会显示为泄漏,但它并不能解释"总堆使用率"为零,因为这描述了所做的和已释放的总分配.

  2. 也许valgrind只是没有在你的平台上工作.如果您构建一个非常简单的程序,如下所示,并valgrind在您的平台上运行,会发生什么?如果这不起作用,您需要找出为什么 valgrind不能正常运行.请注意,valgrind在MIPS上是非常新的.是一个电子邮件主题,MIPS和uclibc发现的开发人员valgrind不会报告任何分配.他的解决办法是更换ntpllinuxthreads.

.

#include <stdio.h>
#include <stdlib.h>
int
main (int argc, char **argv)
{
  void *p = malloc (100);       /* does not leak */
  void *q = malloc (100);       /* leaks */
  free (p);
  exit (0);
}
Run Code Online (Sandbox Code Playgroud)


abl*_*igh 5

(在OP获得第一笔奖金后,问题本身已经发生了重大变化)

根据我对您编辑的理解,您现在拥有:

  1. valgrind自己的测试程序复制问题
  2. 确认测试程序二进制文件动态链接到 uclibc
  3. 确认LD_PRELOAD正在处理您的系统
  4. 确认(如果仅使用测试程序)这不是来自另一个库的符号干扰

对我而言,这表明valgrind存在错误或与您的工具链不兼容.我发现引用说它应该与你的工具链一起使用,所以这意味着我有一个错误.

因此,我建议您使用此处描述的机制报告错误.也许忽略了你复杂的应用程序,并指出简单的测试程序不起作用.如果您还没有,可以按照此处的说明尝试用户邮件列表.