Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect C memory 'leaks' that are freed on exit

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:

  • Why does my program leak memory?
  • How do I detect memory leaks at exit? (no use for me)
  • How do I detect memory leaks from a core file? (great, but none has a satisfactory answer)

If I was running under Solaris I'm guessing the answer would be 'use this handy dtrace script'.

like image 284
abligh Avatar asked Jun 18 '14 08:06

abligh


2 Answers

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

like image 104
nos Avatar answered Sep 28 '22 03:09

nos


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? .

like image 33
oliver Avatar answered Sep 28 '22 02:09

oliver