Comment by patrick451
1 day ago
> Which is really no different from someone choosing to terminate.
If you std::abort(), you'll get a useful stack trace in the core dump. If you crash from an unhandled exception, you don't. That's a pretty huge difference and is one of the reasons exceptions suck.
That's nice but it's certainly not guaranteed by anything, just something provided by your toolchain or platform. ("Core dumps" aren't even a thing in C++.)
If you're looking for implementation-specific guarantees then you could make that happen with exceptions too. I think on GCC replacing a function like __cxa_throw might be sufficient to let you capture a stack trace?
If you're looking for source-level-only guarantees then another option is to just replace your throw <expr> statements with one that attaches whatever extra info you want. You could literally script this to patch your external repos automatically too. Or heck, maybe you could even just define throw to be a macro that shoves your stack trace into some global variable before actually throwing.
Just FYI, finally in C++ you can add a top-level exception handler and call boost::stacktrace::from_current_exception (https://www.boost.org/releases/1.85.0/), and get a stack trace on exit as helpful as in Python or Java.
> If you std::abort(), you'll get a useful stack trace in the core dump. If you crash from an unhandled exception, you don't. That's a pretty huge difference and is one of the reasons exceptions suck.
All of this is up to the implementation in practice. The codebases I work on generally follow the pattern that exceptions may be thrown but may not be caught*, and thus they practically serve as terminate. And we absolutely get stack traces in our core dumps (Linux, both GCC and clang), and basically all of the complex debugging I do starts with a coredump stacktrace.
* We follow this pattern for a few reasons, (1) it is generally safer for us to assume that libraries we consume (STL included) will behave as expected with exceptions enabled, (2) "don't catch exceptions" (or if you must, catch the as close-to-throw as possible) is a simple way to avoid exceptions-for-nonexceptional-cases control flow, and (3) most of the C++ codebase is exposed through bindings in Python, and propagating errors as exceptions is the only Python-friendly way to handle it.
> If you crash from an unhandled exception, you don't.
.. you absolutely get a stack trace from unhandled exception in c++, that starts where the exception is thrown? At least with clang and GCC, maybe MSVC isn't able to.
foo.cpp:
running:
it's a basic example, but it's how I've always done all my debugging in C++ since forever
Sure, in a desktop program you do. In embedded exceptions are a scourge because they crash your program until someone can get back out there to power cycle it. At least with return-codes you can continue execution even if you failed to effect the change you wanted. If that was ancillary to the system’s core function then the system keeps running.
Pretty sure esp32 just rebooted automatically when unhandled exception is thrown for instance