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