Consider the following horribleness:
#include <iostream>
struct thing
{
thing()
{
std::cout << "thing ctor\n";
throw 5;
}
};
void SomeTerminateHandler()
{
std::cout << "Uncaught exception!?\n";
}
int IHopeThisGetsCalledFirst()
{
std::cout << "IHopeThisGetsCalledFirst()\n";
std::set_terminate(SomeTerminateHandler);
return 2;
}
const int x = IHopeThisGetsCalledFirst();
const thing y;
int main()
{
}
Output:
IHopeThisGetsCalledFirst()
thing ctor
Uncaught exception!?
This relies on static initialization order (which I can mess with, for MSVS anyway) so it’s not ideal even if the following questions have acceptable answers.
- What can I do in
SomeTerminateHandlerto ‘catch’ the exception so I can display an error dialog box or log out the details of the error? abortis called afterSomeTerminateHandlerin the above program. Why? This says “The terminate handler by default calls cstdlib’s abort function.” – but I’m not using the default terminate handler, and mine doesn’t callabort.
Is there anything I can do to handle exceptions in static initialization time. If not, why not? Why isn’t there something in the language to allow this?
Nothing – only exception handlers can access the thrown exception.
Your terminate handler must not return; the standard (C++11, 18.8.3.1) requires that it “shall terminate execution of the program without returning to the caller” – the page you link to also says the same thing. If you break that requirement, then anything could happen.
You can catch the exception in the constructor; or you can avoid complex static objects.
I can’t answer why, but C++ doesn’t handle complex static objects at all well. Even if your compiler does have non-standard extensions to specify the initialisation order, I suggest avoiding them if at all possible.