After reading through this StackOverflow question: What is the difference between a direct and indirect leak? I was left with the impression that if I fix all Direct Leaks (multiple fix-test passes since an indirect leak may become a direct one after fixing the previous direct leaks) eventually I would end up with 0 leaks.
I'm currently using the Leak Sanitizer (LSAN) and after fixing all Direct Leaks (and some indirect leaks were gone as a result) I'm now left with a bunch of Indirect leaks. Why are there no direct ones? When could this happen? How do I diagnose and fix the remaining leaks?
An indirect leak is a heap object that is reachable by a pointer to its start address, but with all such pointers originating in leaked objects. Leaks can be thought of as trees, with the top-level object the direct leaks and all child objects indirect leaks.
"indirectly lost" means your program is leaking memory in a pointer-based structure. (E.g. if the root node of a binary tree is "definitely lost", all the children will be "indirectly lost".) If you fix the "definitely lost" leaks, the "indirectly lost" leaks should go away.
Valgrind categorizes leaks using these terms: definitely lost: heap-allocated memory that was never freed to which the program no longer has a pointer. Valgrind knows that you once had the pointer, but have since lost track of it. This memory is definitely orphaned.
Finding Memory Leaks With Valgrind When you run your code, you'll need to specify the tool you want to use; simply running valgrind will give you the current list. We'll focus mainly on the memcheck tool for this tutorial as running valgrind with the memcheck tool will allow us to check correct memory usage.
They might be the circular references. As indirect leak is reachable from other leaked blocks, with cyclic dependency e.g. 2 objects have references to each other, and both of them might be unreachable from the roots.
E.g. in Observer pattern, it's easy to keep circular reference if forget to do a deregistration at the end of usage (Lapsed listener problem).
In general it's better to avoid cyclic references. If think in terms of ownership, owner must have references to objects it owns, but not vise versa, circular dependencies are not possible in this case. It's achievable if pass dependencies via constructor, and not allow to assign dependencies via setters. Also e.g. Rust
with borrowing the references makes circular dependencies impossible.
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