I'm using Keil 4.53 for some LPC1766 (ARM Cortex-M3). I tried this simple code:
class Base { public: virtual ~Base() {} }; class Derived : public Base { public: int b; virtual ~Derived() {} };
If I create local instance of Derived (on stack) - everything is fine, code size is about 350 bytes. Debug works fine.
But if I create global or static instance of Derived - code size suddenly increases to 1100 bytes and debug stops after BKPT instruction (and doesn't enter main):
_sys_exit: 0x00000448 4901 LDR r1,[pc,#4] ; @0x00000450 0x0000044A 2018 MOVS r0,#0x18 0x0000044C BEAB BKPT 0xAB 0x0000044E E7FE B 0x0000044E 0x00000450 0026 DCW 0x0026 0x00000452 0002 DCW 0x0002
If set non-zero heap size (it's zero by default), debug starts to work and everything seems fine. The only thing related to this "BKPT 0xAB" that I managed to find was "semihosting". But I can't see any connection between semihosting and using destructor without heap.
If destructor is not virtual, situation is the same (doesn't matter, is it public or protected).
If I make any other method virtual or protected or whatever, everything works fine without heap.
My question is: is it some kind of compiler error or I have some kind of misunderstanding? I don't want to use heap and I don't need any unnecessary code size increase.
Construction and destruction of globals is discussed in the documentation at infocenter.arm.com/.../Chdfiffc.html
The heap use that you're seeing is probably from the call to __aeabi_atexit (which is used to record the correct destruction order).
Do you need the class to have a destructor? Removing it might solve the problem (because there would be no need to register).
Alternatively, and nastier, you could supply your own __aeabi_atexit that did nothing.
I wonder, why __aeabi_atexit is not called, if I do not create destructor myself (and the default destructor is called).
Actually, no, I don't need to use destructors, because I don't use heap and don't allocate memory at all. And if I will use heap, I have to set non-zero size for it anyway.
In fact, I added destructor just because GCC gived me a lots of warnings like "class has virtual functions and accessible non-virtual destructor" and "base class has non-virtual destructor".
So, I got this very strange behavior - for static objects in embedded program (that will never return from main), if i add destructor that does nothing - I need heap. Seemed very funny.
Thank you for your help!
(infocenter.arm.com/.../index.jsp - another link about this case, just for the record - googled it by "__aeabi_atexit")