объект общего указателя удаляется, в то время как экземпляры shared_ptr все еще находятся в области видимости - PullRequest
3 голосов
/ 05 февраля 2012

У меня есть карта STL, которая содержит общие указатели на объекты, которыми манипулируют в нескольких потоках.Объект, которым владеет shared_ptr, удаляется, пока интеллектуальный указатель все еще присутствует в контейнере и / или области действия других функций.Все экземпляры shared_ptr передаются по значению (поэтому это не проблема с неправильным использованием ссылок).Из этого источника у меня сложилось впечатление здесь , что пока существует экземпляр shared_ptr (который был скопирован из существующего shared_ptr), принадлежащий ему объект не будет освобожден.

Здесьв основном то, что я делаю:

/* 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)
}

Что я делаю не так?Я неправильно использую общие указатели или делаю неправильные предположения о том, как они работают?

1 Ответ

12 голосов
/ 05 февраля 2012

Счетчик ссылок для shared_ptr объектов является атомарным; это требуется C ++ 11. Однако не требуется, чтобы std::map операции были атомарными. Они, конечно, нет.

Не гарантируется, что вы можете вставлять из одного потока и удалять из другого, сохраняя целостность содержимого map. Поэтому, если вы не добавите свои собственные мьютексы или какую-либо другую синхронизацию, чтобы предотвратить состояние гонки на самом map, ваш код сломается.

Это не имеет ничего общего с shared_ptr; это только симптом проблемы. Это о map, который их содержит.

...