C++ Exit-Time Destructors(maskray.me)
maskray.me
C++ Exit-Time Destructors
https://maskray.me/blog/2024-03-17-c++-exit-time-destructors
12 comments
I’ve worked with a handful of developers who were just… careless and cavalier about exit-time destructors, global statics, and more generally, what happens when the user exits the app. Race conditions-on-exit, crashes-on-exit and general sloppiness in cleaning up what was allocated. There’s an attitude out there of “who cares what happens after the user hits the X to exit? The process is dying anyway!” I’ve always considered it a pride/craftsmanship issue but it can be hard to get other developers to care about the details of __cxa_atexit, the order that things happen in, and so on. Long way of saying I appreciate this article!
> There’s an attitude out there of “who cares what happens after the user hits the X to exit? The process is dying anyway!”
Why _should_ we care? Even here, you're not providing a technical justification but instead make a quixotic appeal to emotion. I have listened to talks from HFT guys where they claim to deliberately ignore memory leaks if it produces faster code. They just buy more ram, and rely on the OS clean it up at the end of the trading day. Seems reasonable to me.
Why _should_ we care? Even here, you're not providing a technical justification but instead make a quixotic appeal to emotion. I have listened to talks from HFT guys where they claim to deliberately ignore memory leaks if it produces faster code. They just buy more ram, and rely on the OS clean it up at the end of the trading day. Seems reasonable to me.
I totally get that my appeal to aesthetics and craftsmanship probably just doesn’t even remotely resonate anymore with today’s generation of developers who are just looking to cobble something together so they can “crush it in the market, and have a massive exit, bro!”
I always drag out the old Steve Jobs quote to explain my (evidently dying) attitude about Invisible Quality: “When you’re a carpenter making a beautiful chest of drawers, you’re not going to use a piece of plywood on the back, even though it faces the wall and nobody will ever see it. You’ll know it’s there, so you’re going to use a beautiful piece of wood on the back. For you to sleep well at night, the aesthetic, the quality, has to be carried all the way through.”
I always drag out the old Steve Jobs quote to explain my (evidently dying) attitude about Invisible Quality: “When you’re a carpenter making a beautiful chest of drawers, you’re not going to use a piece of plywood on the back, even though it faces the wall and nobody will ever see it. You’ll know it’s there, so you’re going to use a beautiful piece of wood on the back. For you to sleep well at night, the aesthetic, the quality, has to be carried all the way through.”
Not just today’s generation, there’s always been a quality issue and attitudes like “It works on my computer”. Been a frustration of mine, along with it generally takes more effort to do it wrong.
The primary reason is to make it easier to detect memory leaks.
The article fails to mention that __cxa_atexit allocates and therefore can fail, but the interface does not permit error reporting. This is probably more important to address for the thread-local destructor registration (__cxa_thread_atexit).
Note that this does not create a memory leak, since the pointer/reference is part of the root set.
What does valgrind say?The other way to prevent all destructors running is _exit(0);
I tend to add that to software I write inside an #ifdef NDEBUG.
The OS does the work faster.
I tend to add that to software I write inside an #ifdef NDEBUG.
The OS does the work faster.
std::quick_exit() also works, though you can decide if it's worthwhile to allow parts of the program to register functions to be called at quick exit time.
> A &g = *new A;
> Note that this does not create a memory leak, since the pointer/reference is part of the root set.
Can someone explain this to me? How would that not be a memory leak? What does 'root set' mean in this context?
> Note that this does not create a memory leak, since the pointer/reference is part of the root set.
Can someone explain this to me? How would that not be a memory leak? What does 'root set' mean in this context?
That's not a memory leak (when done at top level) because it's reachable for the entire execution of the program. Memory is only leaked if it's still allocated once it's no longer reachable.
Memcheck disagrees: https://developers.redhat.com/blog/2021/04/23/valgrind-memch...
Technically, this is still a memory leak, it's just considered less serious.
Technically, this is still a memory leak, it's just considered less serious.