我使用经过检查的STL实现在我的代码中出现意外的断言故障。
经过一些研究后,我将问题缩小到了一个向量中的push_back,该向量来自与创建向量的线程不同的线程。
重现此问题的最简单的代码是:
class SomeClass
{
private:
std::vector<int> theVector;
public:
SomeClass ()
{
theVector.push_back(1); // Ok
}
void add()
{
theVector.push_back(1); // Crash
}
};
唯一的区别是SomeClass是从我的主线程实现的,而add是从另一个线程调用的。然而,没有一个简洁的问题:在我用于排除故障的最简单的代码形式中,除了我上面提到的情况之外,没有人从这个向量中读取或写入。
跟踪push_back代码,我注意到std :: vector中的一些方法(如count()或size())返回垃圾,当它从另一个thred(方法“add”)调用时,并且从调用时调用正确的值创建线程(例如在构造函数中)
我是否应该断定std :: vector在多线程环境中不可用?或者是否有解决此问题的方法?
编辑:删除易失性
编辑2:你认为这个问题可能不在于多线程吗?在我的测试运行中,add只被调用一次(使用断点验证)。如果我从构造函数中删除push_back,我仍然会崩溃。所以最后,即使只调用一个向量的方法,在一次调用的函数中也会使断言失败。因此,不能有可靠性,或......?答案 0 :(得分:8)
std::vector
绝对可以在多线程环境中使用,前提是您不能同时从两个线程访问向量。我一直都没有遇到麻烦。
由于vector
不是问题,因此您需要更仔细地查看同步机制,因为这很可能是问题所在。
我注意到您将vector
标记为volatile
。您是否期望将其volatile
提供同步?因为它不会。 See here for more information
答案 1 :(得分:2)
如果你可以保证在调用push_back时没有人写入或读取向量,那么就没有理由它会失败。您可能正在处理更高级别的内存损坏。您应该验证“this”指向SomeClass的真实实例,检查其他成员等。
答案 2 :(得分:1)
标准库是否支持多线程是实现定义的。您必须阅读特定编译器的文档。
另外,你可以做的是添加一些日志消息,如下面的代码所示:
class SomeClass
{
private:
volatile std::vector<int> theVector;
public:
SomeClass ()
{
std::cout << "SomeClass::SomeClass" << std::endl;
theVector.push_back(1); // Ok
}
~SomeClass ()
{
std::cout << "SomeClass::~SomeClass" << std::endl;
}
void add()
{
std::cout << "SomeClass::add" << std::endl;
theVector.push_back(1);
}
};
确保在调用SomeClass
函数时,add
的实例仍然存在。
答案 3 :(得分:1)
大多数STL实现都不是线程安全的。您需要使用线程同步(例如互斥)来防止两个线程在访问向量时互相踩踏。基本上,您需要做的是创建一个包含向量的类,以及保护向量以进行读写操作的互斥锁和访问器函数。