cpp_weekly icon indicating copy to clipboard operation
cpp_weekly copied to clipboard

static **destruction** order fiasco

Open carlosgalvezp opened this issue 2 years ago • 4 comments

Channel

C++Weekly

Topics

Recently a great episode on the "static initialization order fiasco" was presented. However it only covered the fiasco related to "initialization". But what most people forget, is that there are similar problems at destruction time. This is particularly tricky when there are cases where "initialization" is perfectly defined, but "destruction" is not. One example of that is having a static function-local variable - it's initialized when the function is called (well-defined), but it's destroyed after the program ends in indeterminate order. It would be great to show an example of how this subtlety can make a program fail/crash!

Length

5-10 minutes is fine!

carlosgalvezp avatar Jun 28 '23 09:06 carlosgalvezp

I believe the premise of this topic is incorrect.

All static variables are destroyed in the opposite order of construction. You might not know what order an object is going to begin its lifetime, due to multiple translation units, but once that construction order is established, you know the destruction order will be in reverse.

See here: https://eel.is/c++draft/basic.start.term#3

from a practical standpoint, this is because the atexit handler is used to register all destructor calls for static objects

https://eel.is/c++draft/basic.start.term#1

And atexit is required to call all functions in reverse order from registration:

https://en.cppreference.com/w/cpp/utility/program/atexit

lefticus avatar Jul 06 '23 18:07 lefticus

Thanks for the reply, and great to know that the behavior is actually well defined! I would still argue it's "error-prone" since it may not be obvious from the code in which order each static object is created.

I also found the following quote from isocpp:

For example, if there are 3 static objects, say a, b and c, that use ans during their destructors, the only way to avoid a static deinitialization disaster is if ans is destructed after all three.

https://isocpp.org/wiki/faq/ctors#construct-on-first-use-v2

Looking forward to hear your opinions on that! 😊

carlosgalvezp avatar Jul 06 '23 19:07 carlosgalvezp

In my mind (but maybe because I teach this topic regularly) that's more of just a classic object lifetime problem. The order is still very well defined, you just weren't paying attention when you set things up.

I could do something like an "object lifetime gone wrong" and show a few of these classic examples.

Or perhaps a "why does my program crash on shutdown?!" episode and show how statics can get us in trouble if we aren't paying attention.

lefticus avatar Jul 14 '23 18:07 lefticus

you just weren't paying attention when you set things up

I agree this is a lifetime problem, but I believe this is a bit of a special case, because when using static variables there's the implicit expectation that they "always exist" (from the user perspective) and one can rely on them at any point. In reality it's of course not true, but it's harder to see when reading the code and catch with tools.

Think for example if one creates a Logger class to replace std::cout for printing messages. Expectation is that one can use Logger anywhere without issues (as one can do with std::cout), but it can lead to trouble when e.g. used in a destructor of another static global variable:

struct Foo
{
  ~Foo() { getLogger().log("Foo dtor"); }
}

Example: https://godbolt.org/z/MEGboon4q. Unclear why no tool detects the usage of a member function after the object has been destroyed though...

This is the reason why e.g. std::cout is/was implemented using the Nifty Counter Idiom, to ensure both init and deinit fiasco are not a problem. Maybe that pattern could be an episode on its own? Or perhaps it's something we don't want people to use and maybe better to not even talk about it :)

Or perhaps a "why does my program crash on shutdown?!" episode and show how statics can get us in trouble if we aren't paying attention.

Sounds great!

carlosgalvezp avatar Jul 24 '23 06:07 carlosgalvezp