Toymakerii
Toymakerii

Reputation: 1540

Is there a Valgrind for detecting "Memory Leaks" with Smart Pointers

Our team has recently started to experiment with smart pointers, and I am increasingly concerned about our ability to detect and correct memory leaks.

I understand ( I think. . .) that in the purest sense, smart pointers rarely have true leaks, and if there are, it's generally related to circular references. However, I am afraid this is masking the problem of a memory leak in the sense of being "unwanted and unnecessary memory consumption".

For example, when using traditional raw pointers, if an object fails to properly clean up memory, we could run Valgrind and at the end of the program, anything left was a leak (often this could be a leak that continues to grow during program execution leading to severe problems). . . Now with smart pointers, these all get cleaned up before program exit and Valgrind won't see any lost references to allocated memory.

In general I see the value of smart pointers in helping developers prevent leaks, however we are human and make mistakes, thats why we have debugging tools!

How can we detect unwanted memory growth due to a programming error, like we used to be able to do with Valgrind and raw pointers?

... Edits

1) Foolishly I normally associate Valgrind with Memcheck and that is how I intended to use it above. My apologies for confusion.

2) As an illustration here is an example:

Consider multi-threaded application to process data. The first thread reads input (from disk or network whatever), then passes a data block to another thread running Algorithm Step 1 via a queue, Step1's thread grabs data out of its input queue does its thing and passes the data on to Step2. Repeat until a final thread writes out a result (to disk or network). When all the input data is processed, each thread kills itself after it finishes the last items and the program exits.

Now during execution our footprint grows significantly, assuming we can process data as fast as we ingest it, there must be a leak. Using raw pointers I used to detect this kind of error with Memcheck which would have reported lost or possibly lost blocks of memory at the program end which we could track down and fix.

3) In our haste to learn and apply smart-pointers we probably used "shared_ptr" where as another type may have been more appropriate for our application.

Upvotes: 1

Views: 2796

Answers (3)

Useless
Useless

Reputation: 67772

If there's significant memory growth, you'll see that directly or using valgrind's massif tool.

It's also worth noting that there are many types of smart pointer. You mention circular references, so presumably you're talking about shared_ptr? That's the only case where circular references are a risk - it's not general to all smart pointers.

In general, in order of preference:

  1. avoid (direct) dynamic allocation - use containers or other dedicated types to manage memory
  2. avoid complex ownership and/or lifetimes of dynamically-allocated resources: unique_ptr is easy to reason about
  3. if you must share ownership, that implies your object lifetime is inherently non-deterministic, and thus hard to reason about. However, you can't leak a "shared" object without leaking its owners, so a leak implies some confusion higher up your program structure

    • note that if you have references that shouldn't keep a shared object alive, you should use weak_ptr instead. This also serves to break statically-predictable cycles

Upvotes: 3

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

One thing you have to be aware of with smart pointers is that circular dependencies between classes holding e.g. a std::shared_ptr<> of each other won't be cleaned up properly.

I'm afraid that's a situation not detected with valgrind.

Though such can be resolved using std::weak_ptr<>.

Upvotes: 1

UKMonkey
UKMonkey

Reputation: 6993

As per my answer in c++ char* + std::vector memory leak

There are many definitions of memory leak - and valgrind will not detect things that are still in scope. That's the job of the engineer and debugger. (How can any software guess when you might decide you want to use something that's still in scope?)

Upvotes: 2

Related Questions