gpt4 book ai didi

c++ - 是否存在使用 std::set_terminate 无法捕获 C++ 纯虚函数调用的情况?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:33:43 26 4
gpt4 key购买 nike

在 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();

处理程序工作并生成跟踪数据、堆栈跟踪和核心转储。运行时系统打印

pure virtual method called

对于这个测试。

代码中没有对 set_terminate 的其他调用。测试是在服务器启动并运行时完成的,因此任何可能使我的处理程序 gazumped 的后续调用都应该发生,如果它们要发生的话。然而,在实际服务器中,这不会捕获纯虚拟调用。我能想到的唯一可能导致这种情况的情况是在我之后调用设置终止处理程序。有没有其他方法可以避免我的终止处理程序?

最佳答案

实际上,如果您有未定义的行为,对执行环境或编译的二进制文件的任何更改都可能导致您的代码以不同的方式出现错误行为。

这在更改优化和调试标志时尤其明显,但看似无害的代码更改也注定会触发此问题。

接下来,您的错误可能是一个 heisenbug,意思是与时序/多线程有关吗?

此外,如果在构建/销毁过程中不需要虚拟表,并且实际上从未创建过确切类型的对象,您的编译器可能会完全忽略它们。
因此,尽管析构函数已运行,但您对 foo 的调用同样可能会崩溃或调用 derived::foo

关于c++ - 是否存在使用 std::set_terminate 无法捕获 C++ 纯虚函数调用的情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23111360/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com