Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

object of shared pointer being deleted while instances of shared_ptr are still in scope

I have an STL map that contains shared pointers to objects that are manipulated in multiple threads. The object the shared_ptr owns is being deleted while a smart pointer is still present in the container and/or the scope of other functions. All shared_ptr instances are passed by value (so its not a problem with a misuse of references). I was under the impression from this source here that as long as an instance of shared_ptr exists (that was copied from an existing shared_ptr) the object it owns will not be deallocated.

Here is basically what I'm doing:

/* Remove Event response in Thread A */
std::map<std::string, std::shared_ptr<object>>::iterator it = objects.find(id);
if(it != objects.end())
{
    std::shared_ptr<object> ob = it->second;
    objects.erase(it);

    //Do cleanup work with ob
}

/* Add Event response in Thread B */
std::map<std::string, std::shared_ptr<object>>::iterator it = objects.find(id);
if(it == objects.end())
{
    std::shared_ptr<object> ob(new object(id));
    objects[id] = ob;

    //Do setup work with ob
}

/* Duty Cycle Event response in Thread C (very frequent) */
//Take snapshot of objects so Remove Event does not invalidate iterators of duty cycle
std::map<std::string, std::shared_ptr<object>> temp_objects = objects; 
for(std::map<std::string, std::shared_ptr<object>>::const_iterator it = temp_objects.begin(); it != temp_objects.end(); ++it)
{
    std::shared_ptr<object> ob = it->second;
    //Access violation can (but doesn't always) occur when dereferencing ob (ob is empty)
}

What am I doing wrong? Am I misusing shared pointers or making improper assumptions about how they operate?

like image 428
BigMacAttack Avatar asked Dec 12 '22 05:12

BigMacAttack


1 Answers

The reference count for shared_ptr objects is atomic; this is required by C++11. However, what is not required is that std::map operations are atomic. They're certainly not.

It is not guaranteed that you can insert from one thread and delete from another and still maintain the integrity of the contents of the map. So unless you put in your own mutexes or some other synchronization, to prevent race conditions on the map itself, your code will break.

This has nothing to do with shared_ptr; that's just the symptom of the problem. This is about the map that contains them.

like image 62
Nicol Bolas Avatar answered Dec 31 '22 02:12

Nicol Bolas