views:

546

answers:

7

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!

+2  A: 

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.

Kieveli
Many thanks! There are about 200 thousands lines. So It is hard to check every new... is there any compiler Macro to activate boost's ref check ability(if such ability is exist). The memory is causing by programing logic error about pools, I am sure, but I just can not find it.
You can still have memory leaks with shared_ptrs. Create a cyclic reference, and it'll never get deleted, even if the rest of the app no longer references it. Instant memory leak!
jalf
An reference to an object being incorrectly retained is still a resource leak. This is why GC programs can still have leaks, usually due to the Observer pattern - the observer is on a list instead the observable and never gets taken off it. Ultimately, a `remove` is needed for every `add`, just as a `delete` is needed for every `new`. Exactly the same programming error, causing exactly the same problem. A "resource" is a really just a pair of functions that have to be called an equal number of times with corresponding arguments, and a "resource leak" is what happens when you fail to do that.
Daniel Earwicker
+12  A: 

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.

Roger Pate
+1 For the reference and the short and true answer.
Jonas
+4  A: 

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.

caspin
Thank you very much! I really use weak_ptr as a resource watcher. So I know large amount of shared_ptr<> is existing in memory. I am sure there is no cycles, some module is ill designed, I am trying to find out it.
+2  A: 

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.

macbirdie
A: 

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.

Vladimir Prus
+2  A: 

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

John Morrison
+1  A: 

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 http://stackoverflow.com/questions/67174/find-memory-leaks-caused-by-smart-pointers

iain