Annex F (informative) Core undefined behavior [ub]

F.2 [basic]: Basics [ub.basic]

F.2.22[ub:basic.start.term.use.after.destruction]
Specified in: [basic.start.term]

If a function contains a block-scope object of static or thread storage duration that has been destroyed and the function is called during the destruction of an object with static or thread storage duration, the program has undefined behavior if the flow of control passes through the definition of the previously destroyed block-scope object.
Likewise, the behavior is undefined if the block-scope object is used indirectly (i.e., through a pointer) after its destruction.
[Example 1: struct A {}; void f() { static A a; } struct B { B() { f(); } }; struct C { ~C() { f(); } }; C c; B b; // call to f() in constructor begins lifetime of a int main() {} // undefined behavior, static objects are destructed in reverse order, in this case a then b and // finally c. When the destructor of c is called, it calls f() which passes through the definition of // previously destroyed block-scope object — end example]