2

我已经走到了尽头:我有一个单线程 C++ 程序。这里是一些经验数据和背景信息,我试图突出最重要的关键词;

  • 我正在谈论的整个部分没有任何系统调用,除了标准 C++ 库可能执行的内存(取消)分配调用(std::set涉及 s)。这是一个纯粹的逻辑算法。
  • 这个行为应该是确定性的,取决于输入,我不会改变。
  • 如果 bug 出现,程序就会陷入看起来像是无限循环的状态,它似乎开始分配超出任何界限的内存
  • 该错误不会可预测的方式表现出来,我可以从命令行运行程序,有时(可能 30%-50%)该错误会表现出来,否则,据我所知,一切运行顺利且正确。
  • 一旦我不是直接从提示符运行程序,而是在gdb 或 valgrind 中运行程序,错误就消失了,程序永远不会死。
  • 现在是最好的部分:我将问题追溯到(模板化的)非虚拟成员函数调用。就在通话之前,我向 打印一条消息std::cout我可以在终端中看到该消息。函数内的第一行还有一条调试消息,它从未显示

我再也看不到任何合理的解释了。也许你可以想出一个如何进行的想法。


编辑:重要的代码行,我更改了行号,以便我们可以参考它们并省略不相关的部分,因此并非所有内容似乎都是最有意义的。

a.cpp

 10     std::set<Array const*>* symbols;
 11     std::set<Array const*> allSymbols;
 12     symbols = &allSymbols;
 //  ... allSymbols are populated with std::inserter
 15     std::cout << "eval; cd = " << &cd << ", cg = " << &cd.cg << std::endl;
 16     senderConstraints = cd.cg.eval(*symbols);

b.cpp

 31     template <typename ArrayContainer>
 32     ConstraintList eval(ArrayContainer const request) {
 33       std::cout << "inside eval ... going to update graph now" << std::endl;

最后一行输出是:

eval; cd = 0x2e6ebb0, cg = 0x2e6ebc0

然后它被困在无限循环中。

4

1 回答 1

5

我敢打赌,当您更改时,将打印第二行

ConstraintList eval(ArrayContainer const request)

ConstraintList eval(ArrayContainer const & request)

如果是这样,要么allSymbols在第 12 行和第 15 行之间的状态已损坏,要么您的代码看起来更像这样:

std::set<Array const*>* symbols;
{
    std::set<Array const*> allSymbols;
    symbols = &allSymbols;
    //  ... allSymbols are populated with std::inserter
}
std::cout << "eval; cd = " << &cd << ", cg = " << &cd.cg << std::endl;
senderConstraints = cd.cg.eval(*symbols);

这是 UB,因为符号指的是已经破坏的对象。

于 2012-06-26T11:22:07.657 回答