单线程C++函数调用中的undebuggable非确定性heisenbug

bit*_*ask 2 c++ debugging object-lifetime non-deterministic heap-corruption

我在这里结束了:我有一个单线程的C++程序.这里有一些经验数据和背景信息,我试图突出最重要的关键词;

  • 我正在谈论的整个部分没有任何系统调用,除了标准C++库可能执行的内存(de-)分配调用(std::set涉及到).这是一个纯粹的逻辑算法.
  • 这种行为应该是确定性的,取决于输入,我不会改变.
  • 如果错误表现出来,那么程序就会陷入无限循环,它似乎开始分配超出任何界限的内存.
  • 该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);
Run Code Online (Sandbox Code Playgroud)

b.cpp

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

最后一行输出是:

eval; cd = 0x2e6ebb0, cg = 0x2e6ebc0
Run Code Online (Sandbox Code Playgroud)

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

Hen*_*rik 5

我打赌,当你改变时,第二行被打印出来

ConstraintList eval(ArrayContainer const request)
Run Code Online (Sandbox Code Playgroud)

ConstraintList eval(ArrayContainer const & request)
Run Code Online (Sandbox Code Playgroud)

如果是这样,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);
Run Code Online (Sandbox Code Playgroud)

这是UB,因为符号指的是已被破坏的对象.