Dr. Memory: A Memory Checker Faster Than Valgrind
drmemory.org
drmemory.org
It's orders of magnitude faster than valgrind - and it can find bugs that are simply impossible to find with a runtime-only tool (e.g. most stack oob accesses). However it can't find uninitialized memory (there is msan for that, but that's a bit tricky to set up and not available in gcc).
By the way, there's a great talk from C++ Going Native 2013, called The Care and Feeding of C++'s Dragons [1] talking about a number new C++ tools, including AddressSanitizer. It's been two years since then, but it's probably still a good introduction.
[1] https://channel9.msdn.com/Events/GoingNative/2013/The-Care-a...
http://clang.llvm.org/docs/AddressSanitizer.html#memory-leak...
https://blog.mozilla.org/jseward/2015/10/05/dr-memory-a-memo...
After did it a few times, it normally take less than 1 days to put in the code - basically wrapper for malloc, free, etc, new, delete. Add some table code to track bytes alloc/ free per filename/line#.
It must have a very concise high level table dump memory alloc/free associate with file:lineno.
file:lineno: #Alloc_ByteCnt #Free_ByteCnt
Advantages:
It works very well on app that need to runs forever. One can easily track memory usage/leakage over time, but adding a trigger to dump the memory table without killing the app. The trigger can be TestAPI call or external URL. If you have a full functional regression test coverage system in place (All my projects has them), one can easily trigger the memory table dump along with certain test points. Fairly easy to ID memory leak associate with very high level functionalities such as
* certain image load trigger 200K leak per test loop.
* Certain URL access trigger file:line leak 64 bytes per test loop
* , etc
Once all these setup in place, memory leak are fairly trivial to solved. I have not seen any user space memory leak that take more than 1 hours to solve and verify.
The most complex memory leak I had to debug was the EGL app that trigger EGL kernel driver memory leak at ~20MB per over night testing. To debug that was much harder.....
Because that was the kernel/system memory is leaking not just user APP memory. #include <valgrind/memcheck.h>
...
// in the code:
VALGRIND_DO_LEAK_CHECK;
I like to put #ifdef CONFIG_VALGRIND_SUPPORT
around this stuff so it can be compiled out. The Valgrind API call macros expand to some machine code instruction patterns which execute harmlessly on a regular CPU, and have no effect, but are recognized as triggers by the Valgrind execution core. These instructions add bloat and burn cycles.Valgrind has the advantage that it has a real leak checker: i.e. reports of still-allocated memory that is definitely unreachable by any pointer. It can also report blocks which are reachable only by pointers into their interior, not to their base address.
Having the stack trace for each allocation is also nice. If something is leaked, it can sometimes be useful to know where it was allocated (by what chain of calls). Of course you might know that every dynamic struct foo came from foo_alloc. But who called foo_alloc for a given leaked struct foo? And who called that caller?
:(
They've got experimental 64-bit and ARM support in the repo, but they're still ironing out some false-positives. [1][2]
[1] - https://github.com/DynamoRIO/drmemory/issues/1839
[2] - https://github.com/DynamoRIO/drmemory/commit/dcb3af0836e0d75...
Then they like to carp about exactly how the memory was freed, which primitive etc. Which can matter when multiple heap disciplines are in use. But when they aren't its just more noise.
I remember an embedded fibre channel router we did, 16 processors and 100's of server message handlers. We tried a heap validation tool of some sort (valgrind?) and after a week of struggle we found exactly one sort-of problem ( a small leak ) out of the thousands of false alarms. Definitely not worth the effort.
- still reachable allocated blocks
- possibly leaked blocks: block reachable only via pointers to their interior, not to their base address
- definitely leaked blocks: blocks not reachable by any pointer in the program image.
Even the simplest tools like dmalloc do not report all allocations ever performed as leaks (even ones that have been freed). The simple tools report the still-in-use blocks, regardless of whether they are reachable or not.
That can be "good enough". And anyway, sometimes blocks that are still reachable are de facto leaks. Programs can have "semantic leaks" whereby some dynamic set data structure keeps growing and growing as processing marches on. For instance, a global hash table from which nothing is removed even though the entries have ceased to be relevant and the table is the only thing which refers to them. (Someone forgot to make the hash table a weak hash).
Also, if you are ignoring warnings about using the wrong deallocator in C++ then you are making a big mistake. Your code may work but this causes nasty bugs. E.g. if you allocate with 'new []' and then deallocate with plain old 'delete' or worse 'free()'.
The example about new[]/delete; is a good one. That is important only if the element has a ctor/dtor. Yet the tools flag simple scalar arrays as well - pointlessly adding to the noise.
And no, I don't want to maintain multiple code paths on my system, even for compiled generated AVX[2,512,SSE4.1] code. If you do so, you end up having a dev system unrepresentative of the production one.