【问题标题】:Filtering out junk from valgrind output从 valgrind 输出中过滤掉垃圾
【发布时间】:2015-12-17 01:44:07
【问题描述】:

我正在尝试修复一个非常大的项目中的内存泄漏。基准测试已经确认内存泄漏是一个严重的问题,我正在努力寻找它们的根源。

在一个非常简单的案例上运行该项目,我报告了大约 850 个潜在的内存泄漏。除了大约 5 个之外,所有这些看起来都像:

==83597== 768 bytes in 3 blocks are possibly lost in loss record 743 of 864
==83597==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==83597==    by 0x548EF93: myproject_malloc (mysourcefile.c:48)
==83597==    by 0x4F13FD5: ??? (in /path/to/project/library-version.so)
==83597==    by 0x1101: ???
==83597==    by 0xF7: ???
==83597==    by 0x64D4D87: ???
==83597==    by 0xFFFFFFFFFFFFFFFD: ???
==83597==    by 0x6: ???
==83597==    by 0x4F03BB0: ??? (in /path/to/project/library-version.so)
==83597==    by 0xFFFFFFFFFFFFFFFD: ???
==83597==    by 0x64D4D87: ???


==83597== 920 bytes in 1 blocks are possibly lost in loss record 750 of 864
==83597==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==83597==    by 0x548EF93: myproject_malloc (mysourcefile.c:48)
==83597==    by 0x4F13FD5: ??? (in /path/to/project/library-version.so)
==83597==    by 0xFFEFFFD5F: ???
==83597==    by 0x38F: ???
==83597==    by 0xFFEFFFE5F: ???
==83597==    by 0xF: ???
==83597==    by 0x54542FF: ??? (in /path/to/project/library-version.so)
==83597==    by 0x4F536CA: ??? (in /path/to/project/library-version.so)
==83597==    by 0x64B981F: ???
==83597==    by 0xF: ???
==83597==    by 0x54542FF: ??? (in /path/to/project/library-version.so)


==83597== 1,360 bytes in 1 blocks are possibly lost in loss record 789 of 864
==83597==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==83597==    by 0x548EF93: myproject_malloc (mysourcefile.c:48)
==83597==    by 0x4F13FD5: ??? (in /path/to/project/library-version.so)
==83597==    by 0x1101: ???
==83597==    by 0x547: ???
==83597==    by 0x1F: ???
==83597==    by 0x6584267: ???
==83597==    by 0x547: ???
==83597==    by 0x4F13808: ??? (in /path/to/project/library-version.so)
==83597==    by 0x6584267: ???
==83597==    by 0x6584527: ???
==83597==    by 0x65805FF: ???

我正在努力让 valgrind 提供真实、有用的输出而不是 ???,但这可能是不可能的,我希望能够从 memcheck 获得有用的输出,直到发生这种情况。

一个有用的报告有 > 1 个函数调用来自真实源文件而不是 .so 文件报告(因为每个输出都将 myproject_malloc 报告为潜在的泄漏源)。我可以从输出中删除所有垃圾并在我的 emacs 编译缓冲区中仍将其显示为纯文本的最简单方法是什么?

我知道我可以编写一个几十行长的 Python 脚本来完成这项工作,方法是检查每次输入新的错误报告并计算我看到“.c:\d+”的次数,但是我更喜欢更简单的。

有没有用命令行工具做这件事的好方法?还是我不知道的 valgrind 选项?

【问题讨论】:

    标签: shell parsing emacs valgrind


    【解决方案1】:

    不是一个选项,而是一个配置特性:valgrind可以配置suppression文件,告诉它忽略某些堆栈跟踪。

    有关信息,

    是的!使用--gen-suppressions=yes 功能自动为您吐出抑制。然后,您可以根据需要编辑它们,例如。使用通配符(如“*”)组合类似的自动生成的抑制。

    如果您真的想手动编写抑制,请仔细阅读手册。请特别注意,C++ 函数名称必须经过重整(即不能重整)。

    Valgrind 依赖于符号。那些??? 用于缺少符号(有些似乎不是可能的地址)。我记得,valgrind 提供了那些 after 检查符号,所以(即使有一个合适的通配符可以将 ? 作为元字符),你也不能明确地禁止这些。 p>

    您的堆栈跟踪缺少项目库的行号。如果你用调试(-g)编译并设计一个合适的帧级抑制,那似乎是一种改进。

    【讨论】:

    • 我不想基于源代码进行抑制,因为我关心的堆栈跟踪会通过有问题的库,并且堆栈跟踪从那里开始但进入具有正确显示符号的代码. AFAIK 保存所有信息的唯一方法是根据输出中好符号的数量而不是其他任何东西来抑制。有没有办法做到这一点?
    • 另外,我已经在使用-g 进行编译(据我所知,某个角落可能有一个不听我的 Makefile)--- 我需要这样做的原因这样做是因为我无法让它工作。
    • 我指的是带有/path/to/project/library-version.so 的行。如果那些有调试信息,一个可行的抑制文件将能够更好地引用库中的行号,并对带有问号的堆栈项使用帧级抑制。
    • 这个问题是一个 hack 解决方法,因为我无法从共享库中获取调试信息,即使我传递了适当的选项。 (这是一个巨大的项目,我正在中间接手,所以确保 make 完成我期望的工作并非易事。)
    • @PatrickCollins 你确定最终的库没有被剥离(基本上撤消了-g)吗?应该通过转储库中的符号或在库上运行file 来确认它是否显示not strippedstripped
    【解决方案2】:

    正如我在 cmets 中所说,这里基于来源的抑制不是一种合适的技术,因为我正在使用的库的奇怪属性(几乎每个堆栈跟踪都通过“坏”库 library-version.so 并编译-g 不能解决它)。最后我只写了一个 python 脚本,我会在这里为未来的用户发布:

    #!/usr/bin/python
    
    import fileinput
    import re
    
    START = re.compile("in loss record")
    STOP = re.compile("^==\d+== $")
    GOOD = re.compile(r"\.c:\d+", re.M)
    
    def main():
      in_line = False
      current = []
      for line in fileinput.input():
        if in_line:
          in_line = not STOP.search(line)
        else:
          in_line = START.search(line)
    
        if in_line:
          current.append(line)
        else:
          match = GOOD.findall("".join(current))
          if len(match) > 2:
            print "".join(current)
          current = []
    
    if __name__ == "__main__":
      main()
    

    现在,您可以将 valgrind 输出保存到文件中,也可以将其直接通过管道传输到该脚本,这样可以减少繁琐的工作。调整len(match) > FOO 行以控制您保留多少结果。

    【讨论】:

      猜你喜欢
      • 2019-03-10
      • 2010-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-18
      • 1970-01-01
      • 1970-01-01
      • 2014-12-16
      相关资源
      最近更新 更多