Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I trap a pure virtual method called error?

Tags:

c++

gdb

I occasionally get this error

pure virtual method called
terminate called without an active exception
  1. it isn't possible to instantiate an abstract class in C++, so how is it even possible to get this situation
  2. How can I track this error down ? The complication here is that one process launches a child process, so it could be in the child or in the parent.

I've added a number of try/catch blocks to the code, but is there some tool that can help trap this error ?

valgrind is not usable in my situation since this is a high speed encoder with high memory usage, so it takes forever to run.

Any tips or clues would be most welcome.

like image 747
Jacko Avatar asked Dec 13 '25 10:12

Jacko


2 Answers

A possible cause is that you are calling a virtual member function in a constructor or destructor, where virtual function calls don't work yet. This is because:

  • in a constructor, we haven't constructed the derived class that inherits from us yet
  • in a destructor, we have already destroyed the derived class that inherits from us

For example:

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

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

Tracking down the call

This is normally very easy, because compilers can typically detect this and issue a warning:

<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(); }
             ^

If this doesn't work for whatever reason, we can track down calls to Base::foo(), using a debugger and making it stop when std::terminate is called. break abort in GDB should work, because std::terminate calls std::abort by default.

If this isn't possible, we can define a terminate handler using std::set_terminate and put a breakpoint inside.

If this isn't an available option for whatever reason (e.g. C++98 code base), we can define Base::foo() and put a breakpoint inside:

void Base::foo() {
    // breakpoint here
}
like image 136
Jan Schultke Avatar answered Dec 14 '25 23:12

Jan Schultke


In GCC/on systems using the Itanium ABI, you can define the function __cxa_pure_virtual. This is the function that gets called when a pure virtual function would have gotten invoked that doesn't have another definition.

By default, it just prints "pure virtual method called" then terminates. You can make it throw an exception with a stack trace or have a break point:

extern "C" void __cxa_pure_virtual() {
    trap_signal();
    gdb_breakpoint();
    print_stacktrace();
    throw std::runtime_error("pure virtual function called");
}
like image 36
Artyer Avatar answered Dec 15 '25 00:12

Artyer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!