If using C++ on an embedded target, you depend on the constructors for global objects being called by the startup code. While in many cases an embedded system won’t stop, so you don’t need to call the global C++ destructors, this is still something to consider for a proper shutdown.

Constructors at startup
When using the NXP MCUXpresso SDK with C++, the constructors are getting called as you expect it.

This is accomplished by a call to __libc_init_array():
#if defined (__cplusplus)
//
// Call C++ library initialisation
//
__libc_init_array();
#endif
The data necessary to call the destructors is collected by the linker in a section marked with __init_array_start and __init_array_end as with the entry below in the linker file:
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
Unfortunately, things are not setup for the destructors, so we have to configure this manually with the steps below.
Destructors
First, we have to tell in the linker file that we want to collect the information about the destructors. To do this, we have to change the linker script file and to prevent the linker to change it. Go to the project settings and turn off the ‘Manage linker script‘:

With this, the linker won’t change the linker file any more.
Next, add a section with __fini_array_start and __fini_array_end to the linker file:
/* array of function pointers for the the static destructors */
__fini_array_start = .;
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
__fini_array_end = .;
KEEP(*(.fini));
Best to place this right after the __init_array_start:

Next, I have to add -fno-use-cxa-atexit to the compiler options:

Now I can call the destructors as part of the shutdown process, using following interface:
extern "C" {
extern void __libc_fini_array(void);
}
This could be called in the startup code in case it returns from main(), or as part of the exit() code of the application.

That way, all the global objects get released at the end of the application:

Summary
While many embedded applications never shut down, in a clean system design there are ways to power down a system in a proper way. In the case of C++ this includes cleaning things up and calling the destructors oft he global objects too.
Happy destructing š
Links
- Example project on GitHub: https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/MCUXpresso/FRDM-K22F/FRDM-K22F_Cpp_Constructors