__cxa_pure_virtual()
&
Undefined reference to operator delete(void*)
C++ Programming for MCUs such as the Atmel AVR family can be both very productive and also very frustrating as one learns to work without libstdc++ when using certain MCU toolchains e.g.
- C++ AVR Studio
- C++ avr-gcc
- C++ Arduino
Whilst it is generally well known that the MCU programmer must provide their own versions of new and delete[1] it is less well known that the C++ programmer using pure virtual member functions must provide an implementation for __cxa_purevirtual() or face some very confusing errors!
Depeding on toolchain the programmer may be lucky and be notified:
undefined reference to `__cxa_pure_virtual'
What is __cxa_purevirtual()?[2]
Pure virtual functions can get called during object construction/destruction. If that happens, __cxa_pure_virtual() gets called to report the error.
Importantly, __cxa_pure_virtual()is defined in most toolchains as part of libstdc++. However, MCU compiler toolchains do not compile against libstdc++ and so have no definition for new, delete or __cxa_pure_virtual()
Why do I have to define __cxa_purevirtual()?[1][2]
If just writing a C++ interface using pure virtual class member function, then it is not necessary to define new/delete. However...
- Remove the virtual modifier from the base class destructor.
- Ensure that the derived class has an implementation of __cxa_pure_virtual().
In PacketWriter.h
class PacketWriter {
public:
virtual void nextByte() = 0;
protected:
~PacketWriter() {}
};
In StringWriter.h
#include "PacketWriter.h"
class StringWriter : public PacketWriter {
public:
StringWriter(const char* message);
void nextByte();
};
In StringWriter.cpp
#include "StringWriter.h"
// Definition of the error function to call if the constructor goes bonkers
extern "C" void __cxa_pure_virtual() { while (1); }
StringWriter::StringWriter(const char* message){
// constructor code here
}
void StringWriter::nextByte() {
...
}
Compile with
avr-g++ StringWriter.cpp
Why is an infinite loop a good choice?[2]
- safe
- predictable
- obvious a.k.a. "loud error"
An infinite loop would be awkward to debug unless using a debugger that can interrupt execution and give a stack backtrace. It would be more useful to abort the program and report the error but this may well be non-optional in a MCU setting.
No comments:
Post a Comment