// cxxProbe.cpp - full C++ ABI validation incl. dtor invocation. // $025000 = 0xC0DE Singleton ctor (1st inst()) // $025002 = 0x4242 heap value via new + member access // $025004 = 1 Singleton ctor count after 3 inst()s (guard works) // $025006 = 0x6707 global ctor (init_array) // $025008 = 0x900D end of main // $02500A = 0xDEAD Singleton DTOR ran (via __cxa_atexit walk) // $02500C = 0xFEED Global DTOR ran (via __cxa_atexit walk) extern "C" { #include } static int gSingletonCtorCalls = 0; struct Singleton { int n; Singleton() : n(0xC0DE) { gSingletonCtorCalls++; *(volatile uint16_t *)0x025000UL = (uint16_t)n; } ~Singleton() { *(volatile uint16_t *)0x02500AUL = 0xDEAD; } }; static Singleton &inst() { static Singleton s; return s; } struct Heap { int v; Heap(int x) : v(x) {} }; struct GlobalCtor { GlobalCtor() { *(volatile uint16_t *)0x025006UL = 0x6707; } ~GlobalCtor() { *(volatile uint16_t *)0x02500CUL = 0xFEED; } }; static GlobalCtor gGlobal; static volatile Heap *gHeapEscape = nullptr; int main(void) { inst(); inst(); Singleton &s = inst(); (void)s; Heap *h = new Heap(0x4242); gHeapEscape = h; *(volatile uint16_t *)0x025002UL = (uint16_t)gHeapEscape->v; gHeapEscape = nullptr; delete h; *(volatile uint16_t *)0x025004UL = (uint16_t)gSingletonCtorCalls; *(volatile uint16_t *)0x025008UL = 0x900D; return 0; }