одновременное чтение и запись в вектор вызывают исключение - PullRequest
0 голосов
/ 29 июня 2011

У меня есть 2 потока (с помощью библиотеки потоков Boost) и глобальный вектор в Windows (Visual Studio 2005).Я создал потоки - первый читает файл (vector.push_back(value)) и увеличивает «счетчик чтения», другой обрабатывает уже загруженные данные (второй «указатель» запоминает индекс в векторе, который уже обработан).Обработка - это что-то вроде vector[i] = function(vector[i]);

Когда я запускаю программу, она завершается с исключением Unhandled exception at 0x0041350c in program.exe: 0xC0000005: Access violation writing location 0x00b82214. Счетчик чтения имеет значение меньше, чем количество записей (все еще читает файл), vector.size () равен "readCounter"+ 1 "," указатель обработки "+/- 2200 (намного меньше, чем счетчик чтения - нет проблем при чтении пустого значения) ... значения различаются при каждом запуске (иногда не выдается исключение и программа завершается) ...

когда я удаляю строку обработки (vector[i] = function(vector[i]);), никаких проблем не возникает ... поэтому я думаю, вектор не является поточно-ориентированным.Можете ли вы помочь мне, как предотвратить эту проблему?

Ответы [ 3 ]

6 голосов
/ 29 июня 2011

Текущая версия стандарта (C ++ 03) даже не поддерживает потоки, поэтому тот факт, что контейнеры STL являются потокобезопасными или нет, полностью зависит от конкретной реализации.

В вашем случае вам следует обратиться к этой странице MSDN, в которой говорится, что

Один объект является поточно-ориентированным для чтения из нескольких потоков. Например, для объекта A безопасно считывать A из потока 1 и из потока 2 одновременно.

Если один объект записывается одним потоком, то все операции чтения и записи в этот объект в том же или других потоках должны быть защищены. Например, если для объекта A задан поток 1, записывающий в A, то поток 2 должен быть запрещен для чтения или записи в A.

Таким образом, вы должны защищать свои операции чтения / записи с помощью мьютекса или другого примитива синхронизации. Вы можете найти мультиплатформенную и C ++-дружественную реализацию их в Boost.Thread (кстати, это библиотека, на которой основана поддержка потоков в C ++ 0x).

<ч />

Кстати, если вам когда-либо приходилось использовать предыдущую версию VC ++ (например, 2003), помните, что в этих версиях доступна как многопоточная, так и однопоточная версия стандартной библиотеки. Никогда не следует использовать однопоточную версию CRT, если вы используете потоки и средства CRT в своем приложении, всегда проверяйте в настройках проекта, чтобы убедиться, что выбрана правильная версия.

0 голосов
/ 29 июня 2011

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

Тем временем вы пытаетесь записать какое-то значение в адрес памяти, который вам больше не принадлежит ...

Если вы знаете, насколько большой он будет расти, вы можете предварительно выделить всю необходимую память.Это дает дополнительное преимущество: ему не нужно копировать его снова и снова, поскольку он удваивает свой размер.

См .: vector :: vector , vector ::acity , вектор :: резерв

0 голосов
/ 29 июня 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...