After answering this question and not finding a satisfying answer in the standard paper, I started wondering. The standard states the following w.r.t. initialization of mentione
The C++ specification can only define things that are contained within the C++ specification. Remember: the C++ specification defines the behavior of a virtual machine it defines. And if it doesn't define that something can happen, it certainly doesn't define the behavior of C++ around that something that it doesn't say can happen.
According to the C++ specification, a thread can exit in exactly three ways: by returning from its main function, throwing an exception through its main function, and direct process exiting (as with std::terminate
or similar functions). In short, a C++ thread cannot exit in any other way. There is no ExitThread
function in standard C++. Similarly, std::thread
cannot kill a thread, either externally or internally.
Therefore, anything that does cause this thing that C++ says can't happen is, by definition undefined. I guess it wouldn't even be "undefined behavior"; it would be in that nebulous space that threading was in before C++11 actually laid down how thread interactions worked.
The same goes for "signals", whatever those are. The C++ spec doesn't say that those can cause a function to exit. Here be dragons.
As for longjmp
, that's covered by the behavior of longjmp
. When you use longjmp
to exit a function, that function never finished, just as if you used throw
and catch
. And in C++, an object is only constructed when its constructor has completed. Therefore the object's initialization was never completed, and it is uninitialized.
I don't have the ISO C specification (which C++ references for the behavior of longjmp
), but C++11 does strongly suggest that you can equate throw
/catch
with longjmp
/setjmp
, as far as when you get undefined behavior:
§18.10 [support.runtime] p4:
The function signature longjmp(jmp_buf jbuf, int val) has more restricted behavior in this International Standard. A setjmp/longjmp call pair has undefined behavior if replacing the setjmp and longjmp by catch and throw would invoke any non-trivial destructors for any automatic objects.
So I don't think this is underspecified. It may not be nicely and neatly laid out, but all of the pieces are there.