如何捕获名为错误的纯虚方法?

问题描述 投票:0回答:3

我偶尔会收到此错误

pure virtual method called
terminate called without an active exception
  1. 在 C++ 中实例化抽象类是不可能的,那怎么可能呢? 得到这种情况
  2. 如何追踪此错误? 这里的复杂之处在于,一个进程启动一个子进程,因此它可能位于子进程中,也可能位于父进程中。

我在代码中添加了一些 try/catch 块,但是有一些工具可以帮助捕获此错误吗?

valgrind 在我的情况下不可用,因为这是一个高速编码器,内存使用量很高,因此需要永远运行。

任何提示或线索将非常受欢迎。

c++ gdb
3个回答
5
投票

一个可能的原因是您在构造函数或析构函数中调用虚拟成员函数,其中虚拟函数调用尚不起作用。 这是因为:

  • 在构造函数中,我们还没有构造从我们继承的派生类
  • 在析构函数中,我们已经销毁了继承自我们的派生类

例如:

struct Base {
    Base() { foo(); } // undefined behavior
    virtual void foo() = 0;
};

struct Derived : Base {
    void foo() final {}
}

追踪来电

这通常非常简单,因为编译器通常可以检测到这一点并发出警告:

<source>:2:14: warning: call to pure virtual member function 'foo' has undefined behavior;
                        overrides of 'foo' in subclasses are not available in the
                        constructor of 'Base' [-Wcall-to-pure-virtual-from-ctor-dtor]
    Base() { foo(); }
             ^

如果由于某种原因这不起作用,我们可以使用调试器跟踪对

Base::foo()
的调用,并使其在调用
std::terminate
时停止。 GDB 中的
break abort
应该可以工作,因为
std::terminate
默认调用
std::abort

如果这是不可能的,我们可以使用

std::set_terminate
定义一个终止处理程序,并在里面放置一个断点。

如果出于某种原因这不是一个可用的选项(例如 C++98 代码库),我们可以定义

Base::foo()
并在其中放置一个断点:

void Base::foo() {
    // breakpoint here
}

3
投票

在使用 Itanium ABI 的 GCC/on 系统中,您可以定义函数

__cxa_pure_virtual
。这是当调用没有其他定义的纯虚函数时调用的函数。

默认情况下,它只打印“调用的纯虚拟方法”然后终止。您可以让它通过堆栈跟踪抛出异常或设置断点:

extern "C" void __cxa_pure_virtual() {
    trap_signal();
    gdb_breakpoint();
    print_stacktrace();
    throw std::runtime_error("pure virtual function called");
}

0
投票

你能用这个方法捕获错误吗?我似乎偶尔会遇到类似的错误,并且似乎没有从构造函数或析构函数中调用虚函数,但很难定位错误。

© www.soinside.com 2019 - 2024. All rights reserved.