Boost logo

Boost Users :

Subject: [Boost-users] [multi-index] Container not safe against reentrant clear() / erase() ?
From: Sebastian Theophil (stheophil_at_[hidden])
Date: 2009-06-03 09:28:23


Hi,

 

I have encounted a scenario that triggers an access violation when
removing reference counted objects from a container.

 

Assume I have a (for simplicity's sake, global) multi_index_container
g_multiindex containing reference counted objects of type CObject:

 

boost::multi_index_container< ordered_unique< shared_ptr<CObject> > >
g_multiindex;

 

In general, an object of type CObject may be destroyed at any time and
the destructor makes sure to remove any reference held in g_multiindex:

 

class CObject {

    ~CObject() {

         // if object is explicitly destroyed, remove from container

         g_multiindex.erase( this );

    }

};

 

Since ownership of CObject is shared, g_multiindex may hold the last
reference to a CObject instance.

g_multiindex.clear then calls

- delete_all_nodes()

  - delete_all_nodes(root())

    - this->final_delete_node_(static_cast<final_node_type*>(x));

      - which first calls the destructor on x (i.e. it calls ~CObject()
on the root() node)

 

At this point, the multi_index_container is not in a valid state. The
root() node is being deleted but the container still contains the root()
node and points to it, empty() would certainly still return false.
Calling g_multiindex.erase with a compatible key crashes in my case.

 

In general, it seems to me that it would be safer to implement clear()
by doing something like:

 

void clear() {

   multi_index_container cpy;

  swap(cpy, *this);

  cpy.clear();

}

 

This would remove all elements from the container before actually
deleting them. I'm unsure though how the same behavior could be achieved
when erasing a single element.

 

The C++ standard does not seem to define how clear() and erase() should
behave in this regard, but I cannot image that my application scenario
is so unusual that this problem has not been solved a million times. So
I'm curious if the behavior of multi_index_containers is by design and
maybe someone could be so kind to enlighten me why this is so. Is there
any better way to achieve what I'm trying to do?

 

 

Thank you very much,

Sebastian

--
Sebastian Theophil . stheophil_at_[hidden]
Software Engineer
 
think-cell Software GmbH . Invalidenstr. 34 . 10115 Berlin, Germany 
http://www.think-cell.com . phone +49-30-666473-10 . toll-free (US) +1-800-891-8091
Directors: Dr. Markus Hannebauer, Dr. Arno Schoedl . Amtsgericht Berlin-Charlottenburg, HRB 85229


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net