Assume I have a C program (running under Linux) which manipulates many data structures, some complex, several of which can grow and shrink but should not in general grow over time. The program is observed to have a gradually increasing RSS over time (more so than can be explained by memory fragmentation). I want to find what is leaking. Running under valgrind
is the obvious suggestion here, but valgrind
(with --leak-check=full
and --show-reachables=yes
) shows no leak. I believe this to be because the data structures themselves are correctly being freed on exit, but one of them is growing during the life of the program. For instance, there might be a linked list which is growing linearly over time, with someone forgetting to remove the resource on the list, but the exit cleanup correctly freeing all the items on the list at exit. There is a philosophical question as to whether these are in fact 'leaks' if they are freed, of course (hence the quote marks in the question).
Are there any useful tools to instrument this? What I'd love is the ability to run under valgrind
and have it produce a report of current allocations just as it does on exit, but to have this happen on a signal and allow the program to continue. I could then look for what stack trace signatures had growing allocations against them.
I can reliably get a nice large 'core' file from gdb
with generate-core-file
; is there some way to analyse that off-line, if say I compiled with a handy malloc()
debugging library that instrumented malloc()
?
I have full access to the source, and can modify it, but I don't really want to instrument every data structure manually, and moreover I'm interested in a general solution to the problem (like valgrind
provides) rather than how to address this particular issue.
I've looked for similar questions on here but they appear all to be:
If I was running under Solaris I'm guessing the answer would be 'use this handy dtrace
script'.
Valgrind includes a gdbserver. This basically means you can use gdb to connect to it, and e.g. issue a leak dump, or to show all reachable memory while running. Ofcourse, you have to judge whether there is a "memory leak" or not, as valgrind can't know if there's a bug in the application logic that fails to release memory, but still keep references to it.
Run valgrind with the --vgdb=yes flag and then run the commands:
valgrind --vgdb=yes --leak-check=full --show-reachable=yes ./yourprogram
gdb ./yourprogram
(gdb) target remote | vgdb
(gdb) monitor leak_check full reachable any
See the docs for more info, here and here
You can also do this programatically in your program
#include <valgrind/memcheck.h>
and at an appropriate place in the code do:
VALGRIND_DO_LEAK_CHECK;
(iirc that'll show reachable memory too, as long as valgrind is run with --show-reachable=yes
There's the Valgrind Massif tool which shows general memory usage of your application, not just for leaked memory. It breaks down malloc()
s and free()
s by calling functions and their backtraces, so you can see which functions keep allocating memory without releasing it. This can be an excellent tool for finding leaks of the type you mentioned.
Unfortunately the tooling around Massif is a bit weird... The ms_print
tool provided with Valgrind is only useful for the most basic tasks; for real work you probably want something that displays a graph. There are several tools for this strewn around the net - see eg. Valgrind Massif tool output graphical interface? .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With