我有一个定义循环缓冲区的类,如下所示:
class cTest
{
public:
boost::circular_buffer<std::vector<std::pair<double, double>>> circDat;
cTest() : circDat(1000)
{
}
};
然后,我创建一个cTest类型的stl向量
std::vector<cTest> vC;
然后,我尝试像这样填充向量:
for (unsigned int i = 0; i < 4; ++i)
{
cTest obj;
vC.push_back(obj);
}
在Debug模式下工作时,在Release中会崩溃(有时,当我从Visual Studio中运行时,会收到Heap Corruption消息)。 boost文档提到,在“调试”模式下,未初始化的内存填充有“ 0xcc”。我认为,我得到的错误的根源是未初始化的内存。但是我不确定如何解决此问题。
如果使用指针,它似乎可以工作:
std::vector<cTest*> vC;
for (unsigned int i = 0; i < 4; ++i)
{
cTest* obj = new cTest;
vC.push_back(obj);
}
但是我仍然不知道第一个版本的问题是什么。如果有人知道,我将非常感谢您的帮助。
编辑:
我试图创建一个最小的,可复制的代码,但是失败了。它似乎也随机崩溃,与添加/删除的行并没有真正的关联。然后我偶然发现了Visual Studio 2015中的/ GL标志。
关闭/ GL标志后(在GUI项目中-它可以保留在库项目中),我无法重新创建崩溃。我不知道这是否真的可以解决。但是似乎在Visual Studio 2010中存在类似的问题:
crash-in-program-using-openmp-x64-only
编辑2:
我设法整理了一个最小的工作示例。可以在这里下载代码:
https://github.com/davidmarianovak/crashtest
您需要Boost(我使用1.60)和QT5(我使用5.6.3)。在发行版中构建GoAcquire(/ GL在Visual Studio中处于活动状态)。之后,在Release中构建GoGUI(激活/ GL并使用“ standard”进行链接时代码生成)。构建它之后,运行它,它应该崩溃。
可以通过在“ GoInterface.hpp”第22行中进行更改来避免崩溃:
void fillGraphicsViews(std::vector<cSensorConstruct> vSens);
至
void fillGraphicsViews(std::vector<cSensorConstruct> &vSens);
但是我真的不相信这是问题所在。谁能告诉我,我在做什么错?我为此使用Visual Studio 2015。
最佳答案
我敢打赌,您会忘记迭代器/引用无效。因此,问题不在于显示的代码。
Iterator invalidation rules
这是有道理的,因为您报告指针似乎起作用:即使push_back
导致重新分配,指针也保持不变。
当您不知道向量元素将保持有效时,只需不要坚持对向量元素的引用/重复。
如果向量具有已知的最大大小,则可以通过提前保留容量来“作弊”:
static constexpr size_t MAX_BUFFERS = 100;
std::vector<cTest> vC;
vC.reserver(MAX_BUFFERS); // never more
然后也许要保护不变式:
assert(vC.size() < MAX_BUFFERS);
vC.push_back(obj);