cpp_weekly icon indicating copy to clipboard operation
cpp_weekly copied to clipboard

Can const derived virtual objects really be 100% const?

Open jcw opened this issue 1 year ago • 0 comments

Channel

C++Weekly

Topics

It may be a bit too specialized for this channel, but it's a puzzle which I have been bumping into for some time, and it's really a very straightforward aspect of virtual member functions in C++ if you ask me - so perhaps it's also a useful topic here. The context: const objects, stored in flash memory (i.e. embedded microcontrollers). There's an abstract base class with a virtual destructor, and a bunch of derived classes used mostly as normal stack-or-heap based objects and a common cleanup mechanism.

However, in an attempt to place as much data as possible in flash to reduce the RAM footprint and to reduce startup overhead, some of the objects (tables and bytecode) are const and can live in flash. Evidently, all the C++ code will end up in flash, but the instances will not, because of one very tricky detail: when a destructor of a derived class runs, it ends by replacing the vtable to the one from its base class, before passing control to the base class destructor.

The thing is: these cases are all const, there is no cleanup involved. The embedded main doesn't even exit at all, so the global destructors never need to run. IOW, the instance is created at compile time, and 100% const, yet the compiler (e.g. arm-none-eabi-g++) refuses to place it in a read-only section.

To put it differently: when a class is "const-able" and even "constexpr-able", why can't its instance be 100% compile-time constructed and therefore be placed in a r/o part of the app? (without virtual, it all works as expected)

Length

Bite-sized.

jcw avatar Feb 25 '23 19:02 jcw