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

simultaneous reading and writing to vector cause exception

本文关键字:异常 读取      更新时间:2023-10-16

我在Windows(visualstudio2005)上有两个线程(使用boost线程库)和全局向量。我已经创建了线程——第一个是读取文件(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]);)时,不会出现问题。。。所以我想,向量不是线程安全的。你能帮我吗,如何防止这个问题?

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

在您的情况下,您应该参考MSDN的这一页,其中指出

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

如果一个线程正在写入单个对象,那么在同一个或其他线程上对该对象的所有读取和写入都必须受到保护。例如,给定一个对象A,如果线程1正在向A写入,则必须阻止线程2从A读取或向A写入。

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


顺便说一句,如果您必须使用以前版本的VC++(例如2003),请记住,在这些版本中,标准库既有多线程版本,也有单线程版本。如果在应用程序中使用线程和CRT设施,则永远不应该使用CRT的单线程版本,请始终检查项目设置,以查看是否选择了正确的版本。

所以我想,向量不是线程安全的。

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

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

与此同时,你正试图向一个不再属于你的内存地址写入一些值。。。

如果你知道它会增长到多大,你可以预先分配它所需要的所有内存。这还有一个额外的好处,那就是它不必一次又一次地复制,因为它的大小是原来的两倍。

请参阅:vector::vector,vector:;capacity,vector::reserve