Take the 2-minute tour ×

This question always troubles me especially when I'm programming with Qt. Since Qt uses Object Ownership trees, passing a pointer e.g. via myBoostSharedPtr.get() can implicitly transfer ownership. Now consider the case where some Qt Object gets destroyed and the whole Object Tree is destroyed but the smart-pointer is still alive e.g. as member of a different class. What happens if the smart-pointer gets deleted afterwards ? Double deletion with all the nasty consequences ? Do some smart-pointer implementations prevent this ?

share|improve this question
I actually ran into this type of problem with QSharedPointer which is conceptually very similar to boost's shared_ptr. I wrote a blog entry about my findings: blog.codef00.com/2011/12/15/not-so-much-fun-with-qsharedpointer –  Evan Teran Mar 3 '12 at 6:13
add comment

3 Answers

up vote 13 down vote accepted

I'm so tempted to do a rant on the weaknesses of Qt's memory model where a lot of the API still accepts raw pointers with the expectation that the client allocates it while the QObject that accepted the pointer deletes it.

The answer to your question is undefined behavior. shared_ptr has no mechanism to detect if the pointer is deleted by something other than shared_ptr itself, so it will generally try to free the pointer a second time (calling delete on a dangling pointer). If you want to use shared_ptr, you have to stick with shared_ptr as the sole memory manager. This is true even for Qt's own QSharedPointer.

What I normally did to try to get my code reasonably exception-safe when using something like Qt was to use the now deprecated auto_ptr (unique_ptr replaces it and is much safer if you have C++11 available). It's the only place where I was ever tempted to use auto_ptr before, as it provides a release method.

unique_ptr<QListWidget> widget(new QListWidget(...));
// do stuff with the widget to set it up for your GUI
some_layout.addWidget(widget.release()); // <-- release ownership so that 
                                         // the layout now becomes responsible 
                                         // for memory management
// ^^ auto_ptr works above if we don't have C++11

If you need to keep a persistent pointer to your object after it is already being memory-managed by Qt (ex: a pointer to your widget after you inserted it into a layout), just use a regular pointer. There's not really much better you can do since Qt is now the memory manager for that object.

However, you can detect when the object is destroyed (and therefore when the pointer is invalidated) through the QObject::destroyed signal.

If you want to get really sophisticated, you could build a shared pointer type which only stores subclasses of QObject. Since QObject provides a destroyed signal, this kind of custom smart pointer could detect when QObject is destroyed through the destroy signal and avoid trying to delete the object a second time. However, it might get hairy relying on this signal in multithreaded code, and if you do implement a shared pointer, it can become quite a burden dealing with atomic reference counting, capturing a deletion function at the site the pointer is constructed (to avoid module boundary new/delete mismatches), etc.

share|improve this answer
I don't think you should release in the argument list. If addWidget throws before it takes over the pointer, you've leaked. –  GManNickG Mar 2 '12 at 23:46
@GmanNickG that's a good point. Do you think we should release only after the call succeeds? The way I look at it, the API accepts raw pointers to memory allocated by the client. I figure once I pass it, it's QT's responsibility to call delete on the pointer if an exception occurs in addWidget. Otherwise it's QT leaking and not me as far as I see it, and the documentation doesn't state whether QT tries to handle that condition by deleting the pointer with a local try/catch block in addWidget. If it does and deletes the pointer in addWidget and rethrows, my unique_ptr might call delete.. –  stinky472 Mar 2 '12 at 23:52
@GManNickG ... on a dangling pointer. It would very much depend on what I know about how addWidget is implemented. –  stinky472 Mar 2 '12 at 23:55
I agree the situation is muddled, and it's done so in principle, because a raw pointer simply carries no ownership. You're probably right in that QT, with its decision to use raw pointers, ought to be the one to take ownership as soon as the function is entered. But also knowing that QT has made poor decisions with memory management before, it probably doesn't. You're right, the documentation really ought to say. QT sucks in this regard. –  GManNickG Mar 3 '12 at 0:35
QPointer<> has the property you describe at the end. It detects when the pointer wrapped is deleted by other means and will set itself to NULL when this happens. –  Evan Teran Mar 3 '12 at 6:54
show 2 more comments

Yes, most likely and No they don't and I can't see how they could. You have to rely on the contract that the thing you are passing the pointer to will not take ownership (unless the documentation states it), and if the latter, don't wrap it in a smart pointer on your side.

share|improve this answer
add comment

You can't have a shared ownership between a parent QObject and a smart pointer and prevent one to delete the other, but you can track the deletion of any QObject by using only QWeakPointer (or QPointer).

See http://qt-project.org/doc/qt-4.8/qweakpointer.html#tracking-qobject

Update: With Qt 5, tracking QObjects not managed by QSharedPointer with QWeakPointer is deprecated in favor of QPointer (which is itself undeprecated).

share|improve this answer
You should not. Using QWeakPointer without QSharedPointer was deprecated for very good reasons, same reason it is not in C++11. –  abergmeier Jun 24 '13 at 11:09
@abergmeier I'm not sure why you down-voted instead of just leaving the comment or even updating the answer yourself. Using QWeakPointer for the purpose of QObject tracking was the recommended way at the time of writing. –  alexisdm Jun 24 '13 at 20:22
add comment

Your Answer


