Filtering out junk from valgrind output

时间秒杀一切 提交于 2019-12-20 02:28:18

问题


I'm trying to fix a memory leak in a very large project. Benchmarks have confirmed that memory leaks are a significant problem, and I'm working on finding the source of them.

Running the project on a very simple case, I get ~850 potential memory leaks reported. All but about 5 of them look like:

==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: ???

I'm working on getting valgrind to give real, useful output rather than ???, but it may not be possible, and I'd like to be able to get useful output from memcheck until that happens.

A useful report has > 1 function call reported from a real source file rather than a .so file (because every output reports myproject_malloc as a potential leak source). What's the simplest way I can cut out all of the junk from the output and still display it as plain text in my emacs compilation buffer?

I know I could write a Python script that would be a few dozen lines long to do the job by checking every time I enter a new error report and counting the number of times I see ".c:\d+", but I'd prefer something simpler.

Is there a nice way to do this with commandline tools? Or an option to valgrind that I'm not aware of?


回答1:


Not an option, but a configuration feature: valgrind can be configured with suppression files which tell it to ignore certain stack traces.

For information,

  • 5.1. I tried writing a suppression but it didn't work. Can you write my suppression for me? (Valgrind FAQ):

Yes! Use the --gen-suppressions=yes feature to spit out suppressions automatically for you. You can then edit them if you like, eg. combining similar automatically generated suppressions using wildcards like '*'.

If you really want to write suppressions by hand, read the manual carefully. Note particularly that C++ function names must be mangled (that is, not demangled).

  • Valgrind Suppression File Howto
  • How do you tell Valgrind to completely suppress a particular .so file?
  • Valgrind suppression with using frame-level wildcard (ellipses)

Valgrind relies upon symbols. Those ??? are for missing symbols (and some do not appear likely addresses). As I recall it, valgrind supplies those after checking for symbols, so (even if there were a suitable wildcard to work around ? as a meta character), you could not explicitly suppress those.

Your stack traces lack line-numbers for the project library. If you compile with debugging (-g) and design a suitable frame-level suppression, that seems to be an improvement.




回答2:


As I said in the comments, suppressing based on origin isn't an appropriate technique here because of strange properties of the library I'm working with (almost every stack trace passes through the "bad" library library-version.so and compiling with -g doesn't fix it). I ended up just writing a python script, which I'll post here for future users:

#!/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()

Now you can either save your valgrind output to a file or pipe it directly to this script and it cuts down on the cruft. Adjust the len(match) > FOO line to control how many results you keep.



来源:https://stackoverflow.com/questions/34325305/filtering-out-junk-from-valgrind-output

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!