Question

I use boost::shared_ptr in my application in C++. The memory problem is really serious, and the application takes large amount of memory.

However, because I put every newed object into a shared_ptr, when the application exits, no memory leaking can be detected.

There must be some thing like std::vector<shared_ptr<> > pool holding the resource. How can I know who holds the shared_ptr, when debugging?

It is hard to review code line by line. Too much code...

Thanks very much!

Was it helpful?

Solution

You can't know, by only looking at a shared_ptr, where the "sibling pointers" are. You can test if one is unique() or get the use_count(), among other methods.

OTHER TIPS

The popular widespread use of shared_ptr will almost inevitably cause unwanted and unseen memory occupation.

Cyclic references are a well known cause and some of them can be indirect and difficult to spot especially in complex code that is worked on by more than one programmer; a programmer may decide than one object needs a reference to another as a quick fix and doesn't have time to examine all the code to see if he is closing a cycle. This hazard is hugely underestimated.

Less well understood is the problem of unreleased references. If an object is shared out to many shared_ptrs then it will not be destroyed until every one of them is zeroed or goes out of scope. It is very easy to overlook one of these references and end up with objects lurking unseen in memory that you thought you had finished with.

Although strictly speaking these are not memory leaks (it will all be released before the program exits) they are just as harmful and harder to detect.

These problems are the consequences of expedient false declarations: 1. Declaring what you really want to be single ownership as shared_ptr. scoped_ptr would be correct but then any other reference to that object will have to be a raw pointer, which could be left dangling. 2. Declaring what you really want to be a passive observing reference as shared_ptr. weak_ptr would be correct but then you have the hassle of converting it to share_ptr every time you want to use it.

I suspect that your project is a fine example of the kind of trouble that this practice can get you into.

If you have a memory intensive application you really need single ownership so that your design can explicitly control object lifetimes.

With single ownership opObject=NULL; will definitely delete the object and it will do it now.

With shared ownership spObject=NULL; ........who knows?......

One solution to dangling or circular smart pointer references we've done is customize the smart pointer class to add a debug-only bookkeeping function. Whenever a smartpointer adds a reference to an object, it takes a stack trace and puts it in a map whose each entry keeps track of

  1. The address of the object being allocated (what the pointer points to)
  2. The addresses of each smartpointer object holding a reference to the object
  3. The corresponding stacktraces of when each smartpointer was constructed

When a smartpointer goes out of scope, its entry in the map gets deleted. When the last smartpointer to an object gets destroyed, the pointee object gets its entry in the map removed.

Then we have a "track leaks" command with two functions: '[re]start leak tracking' (which clears the whole map and enabled tracking if its not already), and 'print open references', which shows all outstanding smartpointer references created since the 'start leak tracking' command was issued. Since you can see the stack traces of where those smart pointers came into being, you can easily know exactly who's keeping from your object being freed. It slows things down when its on, so we don't leave it on all the time.

It's a fair amount of work to implement, but definitely worth it if you've got a codebase where this happens a lot.

You may be experiencing a shared pointer memory leak via cycles. What happens is your shared objects may hold references to other shared objects which eventually lead back to the original. When this happens the cycle keeps all reference counts at 1 even though no one else can access the objects. The solution is weak pointers.

Try refactoring some of your code so that ownership is more explicitly expressed by the use of weak pointers instead of shared pointers in some places.

When looking at your class hierarchy it's possible to determine which class really should hold a shared pointer and which merely needs only the weak one, so you can avoid cycles if there are any and if the "real" owner object is destructed, "non-owner" objects should have already been gone. If it turns out that some objects lose pointers too early, you have to look into object destruction sequence in your app and fix it.

You're obviously holding onto references to your objects within your application. This means that you are, on purpose, keeping things in memory. That means, you don't have a memory leak. A memory leak is when memory is allocated, and then you do not keep a reference to its address.

Basically, you need to look at your design and figure out why you are keeping so many objects and data in memory, and how can you minimize it.

The one possibility that you have a pseudo-memory leak is that you are creating more objects than you think you are. Try putting breakpoints on all statements containing a 'new'. See if your application is constructing more objects than you thought it should, and then read through that code.

The problem is really not so much a memory-leak as it is an issue of your application's design.

I was going to suggest using UMDH if you are on windows. It is a very powerful tool. Use it find allocations per transaction/time-period that you expect to be freed then find who is holding them.

There is more information on this SO answer Find memory leaks caused by smart pointers

It is not possible to tell what objects own shared_ptr from within the program. If you are on Linux, one sure way to debug the memory leaks is the Valgrind tool -- while it won't directly answer your question, it will tell where the memory was allocated, which is usually sufficient for fixing the problem. I imagine Windows has comparable tools, but I am do not know which one is best.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top