C & C++ DISCUSSION

When does a C++ base class need a virtual destructor, and what does it cost on a small MCU?

Started by veerababu virtual destructorpolymorphismvtablememory leakembedded C++
4 replies 248 views 5 participants
Latest activity · 30 Sep 2026

When does a C++ base class need a virtual destructor, and what does it cost on a small MCU?

veerababu C & C++ Forum
#1

I have an interface class Sensor with a virtual read(), and derived classes such as Bme280 that own a buffer allocated in the constructor. Objects are created with Sensor *s = new Bme280; and later destroyed with delete s;. A static analyser warns that Sensor has virtual functions but a non-virtual destructor, and a heap trace shows the derived buffer is never freed.

Why does delete not call the derived destructor here, and is adding virtual expensive on a microcontroller with 32 KB of flash?

Community replies 4

Re: When does a C++ base class need a virtual destructor, and what does it cost on a small MCU?

#2

With a non-virtual destructor, delete s; selects the destructor from the static type of the pointer, which is Sensor. Formally, deleting a derived object through a base pointer whose destructor is not virtual is undefined behaviour. In practice the usual symptom is the one you see: only ~Sensor() runs, ~Bme280() is skipped, and whatever it should have released leaks.

Declare virtual ~Sensor() = default; in the base class. The destructors of all derived classes are then virtual automatically, and delete s runs ~Bme280() first and ~Sensor() after it.

Re: When does a C++ base class need a virtual destructor, and what does it cost on a small MCU?

#3

A useful guideline: a base class destructor should be either public and virtual, or protected and non-virtual. The first form allows deletion through a base pointer. The second forbids it at compile time: with protected: ~Sensor() = default; the statement delete s; on a Sensor * does not compile, while derived objects are still destroyed normally through their own type.

The protected form suits firmware in which all objects are static or live on the stack and nobody should ever delete through the interface. A class with no virtual functions that is not meant to be a base does not need a virtual destructor at all.

Re: When does a C++ base class need a virtual destructor, and what does it cost on a small MCU?

#4

The cost is small once the class has any virtual function. Each object already carries one vtable pointer, 4 bytes on a 32-bit MCU, and the class already has a vtable in flash. With the Itanium-style C++ ABI used by GCC and Clang, a virtual destructor adds two entries to that table, so a few words of flash per class and nothing per object.

There is one embedded-specific surprise. One of those entries is the deleting destructor, which references operator delete, so a virtual destructor can pull the heap deallocation code into the image even if you never write delete. If the binary grows unexpectedly, check the map file; heapless projects often supply their own empty operator delete.

Re: When does a C++ base class need a virtual destructor, and what does it cost on a small MCU?

#5

Smart pointers follow the same rule with one twist. std::unique_ptr<Sensor> calls delete on a Sensor *, so it needs the virtual destructor exactly as a raw pointer does. A std::shared_ptr<Sensor> created from std::make_shared<Bme280>() stores a deleter for the original type and destroys the object correctly even without one, but that is not something to rely on.

Also remember that virtual dispatch is switched off during destruction: inside ~Sensor() the derived part is already gone, and a virtual call resolves to the Sensor version. GCC and Clang have -Wnon-virtual-dtor and -Wdelete-non-virtual-dtor to catch the original bug at compile time.

TEP COMMUNITY