Opened 17 years ago

Closed 16 years ago

#5 closed Bugs (Fixed)

shared_ptr and self-owning objects

Reported by: nobody Owned by: Peter Dimov
Milestone: Component: smart_ptr
Version: None Severity:
Keywords: Cc:


Consider following program:

#include <boost/smart_ptr.hpp>
#include <iostream>

class foo {
                foo(): m_self(this) { std::cout << "foo
constructor\n"; }
                ~foo() { std::cout << "foo
destructor\n"; }
                void suicide() { m_self.reset(0); }
                boost::shared_ptr<foo> m_self;

int main() {
        foo *foo_ptr = new foo;

When linked with Electric Fence this code fails. This
code invokes undefined behavior in reset method of
shared_ptr: when line if (--*pn == 0) {
checked_delete(px); } executes shared_ptr object gets
destroyed and line *pn = 1 acceses already freed

Why use m_self? 

foo's clients share foo by keeping shared_ptr to it.
foo handles some asynchronous event which may render
foo unneeded to itself (network connection close, for
example), but it still may be needed to clients if any.
OTOH, if no clients use foo at the time of the event
then foo needs to destroy itself. This situation is
best modeled with keeping shared_ptr in foo and letting
foo to reset it when foo thinks it's mission is

The problem with shared_ptr can be solved with small
modification to reset

void reset(T* p=0) {
    T *old_px = px;
    if ( px == p ) return;  // fix: self-assignment
    px = p;
    if (--*pn == 0) {
        *pn = 1;
    else { // allocate new reference counter
        try { pn = new long(1); }  // fix: prevent leak
if new throws
        catch (...) {
            ++*pn;  // undo effect of --*pn above to
meet effects guarantee
            px = old_px; // undo effect of px = p above
        } // catch
    } // allocate new reference counter
} // reset

operator=(const shared_ptr&) and
operator=(std::auto_ptr&) have the same problem and fix
is very similiar. 

Change History (2)

comment:1 Changed 17 years ago by darinadler

Logged In: YES 

Peter Dimov is planning to fix this.

comment:2 Changed 16 years ago by Peter Dimov

Status: assignedclosed
Note: See TracTickets for help on using tickets.