同时读取和写入向量会导致异常

时间:2011-06-28 21:22:00

标签: c++ windows multithreading boost vector

我有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]);)时没有出现问题...所以我猜,vector不是线程安全的。你能帮助我,如何预防这个问题?

3 个答案:

答案 0 :(得分:6)

当前版本的标准(C ++ 03)甚至不支持线程,因此STL容器是否是线程安全的事实完全取决于特定的实现。

在您的情况下,您应该参考MSDN的this page,其中说明了

  

单个对象是从多个线程读取的线程安全的。例如,给定一个对象A,可以安全地从线程1和线程2同时读取A.

     

如果一个线程正在写入单个对象,则必须保护对相同或其他线程上该对象的所有读写操作。例如,给定一个对象A,如果线程1写入A,则必须阻止线程2读取或写入A。

因此,您必须使用互斥锁或其他同步原语来保护读/写。您可以在Boost.Thread中找到多平台和C ++友好的实现(顺便提一下,C ++ 0x中的线程支持所基于的库)。


顺便说一下,如果您曾经使用过VC ++的早期版本(例如2003),请记住,在这些版本中,有标准库的多线程和单线程版本可用。如果在应用程序中使用线程和CRT工具,则不应使用CRT的单线程版本,请务必检查项目设置以查看是否选择了正确的版本。

答案 1 :(得分:0)

  

所以我猜,vector不是线程安全的。

当然std :: vector不是线程安全的(没有一个标准容器可以保证是线程安全的 - 但是所有的方法都保证可以通过每个合理的实现重入)。您必须使用同步机制(互斥锁等)。

答案 2 :(得分:0)

Vector是一种可扩展的数据结构。当然你不能分配任意大内存,所以实现是分配一个固定大小的内存(你可以在构建时设置)。当你push_back元素进入向量时,它会填充这个空间。当它到达预分配空间的末尾时,它必须分配更大的块(通常是原始大小的两倍)并复制其中的所有数据。它还必须更新块开始的内存位置并释放旧的分配空间。

与此同时,您正在尝试将一些值写入不属于您的内存地址......

如果你知道它会增长多大,你可以预先分配它所需的所有内存。这样做的另一个好处是,它不需要一次又一次地复制它,因为它的大小翻了一倍。

请参阅:vector::vectorvector::capacityvector::reserve