是否存在使用std::set_terminate无法捕获C++纯虚拟函数调用的情况
Are there cases where using std::set_terminate does not catch a C++ pure virtual function call?
在Linux服务器上运行的可执行文件的深处,有一个C++纯虚拟函数调用。它导致服务器崩溃,没有留下程序跟踪数据、堆栈跟踪和核心转储。只剩下一些日志文件。几乎可以肯定,这是由一生的问题引起的,我很清楚它发生在哪里,但我想要证据。我试图通过使用std::set_terminate
设置一个处理程序来纠正这种情况,该处理程序在调用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
的调用。测试是在服务器启动并运行时完成的,因此任何可能会占用我的处理程序的后续调用都应该发生,如果它们要发生的话。然而,在实际的服务器中,这确实而不是捕获纯虚拟调用。我能想到的唯一可能导致这种情况是在我的调用之后设置终止处理程序。有没有其他方法可以避免我的终止处理程序?
实际上,如果您有未定义的行为,对执行环境或编译的二进制文件的任何更改都可能导致代码以不同的方式出现错误。
这在更改优化和调试标志时尤其明显,但看似无害的代码更改也会引发这种情况。
接下来,您的错误可能是一个heisenbug,意思是与定时/多线程有关吗?
此外,如果在构建/销毁中不需要虚拟表,并且实际上从未创建过确切类型的对象,那么编译器可能会完全省略这些虚拟表
因此,对foo
的调用可能同样只是崩溃或调用derived::foo
,尽管析构函数已经运行。
相关文章:
- 虚拟决赛作为安全
- PowerPC ppc64le上的Gcc Woverloaded虚拟错误
- 如何在C++中获得"静态纯虚拟"功能?
- C++无法定义虚拟函数 OUTER 类和头文件
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 在模板基类中为继承类中的可选重写生成虚拟方法
- 尝试将unique_ptrs推送到向量时使用纯虚拟函数错误
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 大小虚拟继承中的派生类
- 链接器找不到在虚拟类 c++ 中访问的静态字段的符号
- 使用 C++ 和 i2c 工具从虚拟 i2c 写入和读取
- 重载 -> shared_ptr 个实例中的箭头运算符<interface>,接口中没有纯虚拟析构函数
- 如果整个应用程序是虚拟映射的,为什么 new 会进行系统调用?
- 跨 DLL 边界访问虚拟方法是否安全/可能?
- std::is_trivially_copyable_v 关于虚拟功能
- 删除C++继承中虚拟类成员的代码重复
- 子类地址等于虚拟基类地址?
- 当覆盖存在时调用基本虚拟"binded to object"函数
- 用于创建/注册虚拟存储设备的 IOKit 驱动程序
- 是否可以使用基类非虚拟方法中的派生类虚拟方法?