2014-01-28 3 views
0

Я использую Visual Studio и я получаю исключение на следующей строке кода повышение :: shared_ptr:Многопоточность ошибки в повышение :: shared_ptr код

void release() // nothrow 
{ 
    if(BOOST_INTERLOCKED_DECREMENT(&use_count_) == 0) 
    { 
     dispose(); 
     weak_release(); 
    } 
} 

Я думаю, что это многопоточность, потому что это очень случайный, когда это происходит. Я пытаюсь получить более подробную информацию.

Я разделяю unordered_map<std::string, boost::shared_ptr<MyClass>> среди нескольких тем. Я думаю, что ошибка связана с тем, что разные потоки обращаются к unordered_map в одно и то же время (потоки не имеют доступа к тем же элементам unordered_map).

MyClass содержит unordered_map и набор. Нити добавляют числа к этим структурам данных. Так что если у меня было:

class MyClass{ 
public: 
    void addToMap(double a, long b); 
    void addToSet(double c); 
private: 
    unordered_map<double, long> a; 
    set<double> b; 
} 
  • резьбы 1: Процессы элемент 1 std::unordered_map<std::string, boost::shared_ptr<MyClass> >
  • резьбы 2: Процессы элемент 2 std::unordered_map<std::string, boost::shared_ptr<MyClass> >
  • резьбы 3: Процессы элемент 3 std::unordered_map<std::string, boost::shared_ptr<MyClass> >
  • резьбы 4: обрабатывает элемент 4 из std::unordered_map<std::string, boost::shared_ptr<MyClass> >

У меня нет замков в м y код. Может кто-нибудь, пожалуйста, сообщите, как я могу потенциально решить эту проблему (даже если это означает, что код будет медленнее)? Нужно ли просто вставлять мьютексы внутри каждого объекта MyClass? Однако, похоже, это boost :: shared_ptr объекта MyClass, вызывающего исключение?

Я не передаю никаких boost::shared_ptr объектов по ссылке/указателю.

+0

Объясните, как связаны два фрагмента кода? – Ajay

+0

Вы опубликовали код, в котором функция shared_ptr генерирует исключение, и все же код, который вы опубликовали, не содержит объектов shared_ptr. Это затруднит диагностику. –

+0

@ AndyNewman все, что я вижу, это Visual Studio, ломающееся над этой строкой в ​​заголовке boost_ptr boost. – user997112

ответ

2

operator[] изменяет контейнер и поэтому небезопасен для доступа одновременно. Ваша программа имеет гонку данных. Как правило, функции non-const стандартных объектов библиотеки небезопасны для одновременного доступа. C++ 11 §23.2.2 перечислены некоторые специальные исключения для контейнеров:

В целях предотвращения гонки данных (17.6.5.9), реализации должны рассмотреть следующие функции, чтобы быть const: begin, end, rbegin, rend, front, back, data, find, lower_bound, upper_bound, equal_range, at и, за исключением ассоциативно или неупорядоченных ассоциативных контейнеров, operator[].

Несмотря (17.6.5.9), реализации требуется, чтобы избежать гонки данных, когда содержимое содержащегося в ней объекта в различных элементов в одной и той же последовательности, исключая vector<bool>, изменяются одновременно.

unordered_map Так, это небезопасно для нескольких потоков одновременно звонить operator[] - но это безопасно для них, чтобы получить доступ к различным объектам в контейнере одновременно. Охрана поиска элементов достаточно, например.:

std::unique_lock<std::mutex> lk(some_mutex); 
auto& foo = my_map["key"]; 
lk.unlock(); 
foo += 42; 

В качестве альтернативы, если вы хотите получить доступ к существующим элементам в карте - и не добавлять новые элементы по умолчанию сконструированных - вы можете использовать find без внешней синхронизации на стандартную цитату выше.

+0

Ohhhhhh !!!! Поэтому я должен помещать блокировки мьютекса в начале и конце функций-членов, которые получают доступ к общему unordered_maps через []. Кстати, почему ошибка появляется в коде shared_ptr, а не в коде unordered_map (или где доступ к unordered_map)? – user997112

+0

Должен ли я писать класс оболочки вокруг unordered_map с мьютексами, защищающими функции-члены? – user997112

+0

Теперь есть еще несколько объяснений, что я не на телефоне. Что касается причины ошибки в коде 'shared_ptr', \ * handwaving \ * неопределенного поведения? – Casey

Смежные вопросы