Hasta la vista, baby!
C++ provides surprisingly numerous ways for a program to terminate. These include both normal and unexpected termination. Some older ways are depricated (e.g. std::unexpected()
) and some are new (e.g. §25.2.4.2 algorithms.parallel.exceptions).
When writing robust software and libraries, it is important to be be aware of the various ways your code might abruptly end. Similarly, many of these conditions might occur at module-boundaries such as DLLs.
Amongst the standard C++ program terminators we find:
std::exit()
std::quick_exit()
std::_Exit()
std::abort()
std::terminate()
std::unexpected()
(deprecated)std::signal()
std::raise()
Additionally, OS-specific terminators include:
__fastfail()
[ Microsoft specific ]
Most of these functions have subtle contexts, conditions and effects that should be considered by checking their documentation. Some, but not all, of these functions have facilities for setting and even chaining custom handlers. Some of these handler even have both C and C++ std
versions.
- What happens when you call one of these functions yourself?
- What is the difference between them?
- How are they ordered?
- What are their interdependencies?
- What happens to global and static variables and Singletons?
Come with me if you want to live! (not really)
To better understand all these possibilities, I created a GraphViz diagram showing the various program termination flows as defined by the standard.
The orange path shows normal program termination.
The full res SVG is here.
The diagram repo is here.
The image is taken directly from the repo, so any updates there will be reflected here.
Some notable feature differences between these functions:
Set Return Value | Set Custom Handler via | Has C Version | More | |
---|---|---|---|---|
exit() |
✓ | atexit() |
✓ | Destroys objects |
quick_exit() |
✓ | at_quick_exit() |
✓ | |
_Exit() |
✓ | ✓ | ||
abort() |
✓ | |||
terminate() |
set_terminate() |
|||
unexpected() |
set_unexpected() |
Deprecated | ||
raise() |
signal() |
✓ | ||
__fastfail() |
✓ |
I’ll be back!
This project is already a couple of years old. I’m posting about it since it has recently received renewed attantion due to a flurry of tweets on the subject. Independently, JF Bastien created a project that shows how many of these paths can be invoked and traversed in a program. Check it out here, output here.
This diagram is automatically generated by Graphviz. Other layout apps may give prettier results. I would be happy to learn of them. Corrections, additions, pull-requests, updates and layout improvements will be gladly accepted.
If you found this post amusing, dawnting, surprising, awful etc. do feel free to leave a comment. If you think something is missing or you think more details are required for completeness, leave a comment, open an issue or make a PR.
Acknowledgments: banner :: rawgit.com :: www.tablesgenerator.com :: icon