在Linux服务器上运行的可执行文件的深处,有一个C ++纯虚拟函数调用。这会导致服务器崩溃,不留下程序跟踪数据,堆栈跟踪和核心转储。仅保留一些日志文件。几乎可以肯定,这是由一生的问题引起的,我很清楚发生的地方,但我想证明一下。我试图通过使用std::set_terminate
设置将在调用终止时运行的处理程序来纠正这种情况。这在测试中有效。例如,如果我引起一个纯虚拟呼叫,请使用:
class Base {
public:
Base() {}
virtual ~Base(){}
virtual void foo() = 0;
};
class Derived: public Base {
public:
Derived(): n_(0) {}
~Derived(){}
void foo() {
n_ = 1;
}
private:
int n_;
};
接着
Base* p = new Derived();
Base* p1 = p;
p->~Base();
p1->foo();
处理程序工作并生成跟踪数据,堆栈跟踪和核心转储。运行系统打印
纯虚拟方法称为
对于这个测试。
set_terminate
代码中没有其他调用。该测试是在服务器启动并运行时完成的,因此如果可能的话,任何后续的调用都可能已经使我的处理程序陷入混乱。然而,在实际的服务器,这并没有赶上纯虚拟呼叫。我能想到的唯一情况可能会导致这是在我的调用之后设置终止处理程序。还有什么其他方法可以避免我的终止处理程序?
实际上,如果您具有Undefined Behavior,则对执行环境或编译的二进制文件的任何更改都可能导致您的代码以其他方式出现异常。
在更改了优化和调试标志的情况下,这一点尤其明显,但是似乎无害的代码更改也被预定义为触发此操作。
接下来,您的错误是否可能是heisenbug,即与计时/多线程相关?
此外,如果在构造/销毁过程中不需要虚拟表并且实际上没有创建过确切类型的对象,则编译器可能会完全省略虚拟表。
因此,即使析构函数已运行,您对的调用也foo
可能同样崩溃或调用derived::foo
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句