Are there major C/C++ implementations where the longjmp
function "unwinds", i.e. where it interacts with destructors for automatic-storage objects, __attribute__((__cleanup__(...)))
, POSIX threads cancellation handlers, etc. rather than just restoring the register context saved by setjmp
? I'm particularly interested in the existence (or non-existence) of POSIX implementations with this property, but C/C++ in general are also interesting.
For the bounty, I'm looking for a POSIX-conforming or at least POSIX-like system, as opposed to Windows which has already been mentioned.
Interix (SUA) by default does not call destructors, but in x86 mode, does have an option for it.
Taking this test program, saved as test.cc
:
#include <stdio.h>
#include <setjmp.h>
struct A {
~A() { puts("~A"); }
};
jmp_buf buf;
void f() {
A a;
longjmp(buf, 1);
}
int main() {
if (setjmp (buf))
return 0;
f();
}
here's how Interix behaves. For brevity, I've omitted the required proper setup of PATH
.
$ cc -mx86 test.cc && ./a.out $ cc -mx86 -X /EHa test.cc && ./a.out cl : Command line warning D9025 : overriding '/EHs' with '/EHa' ~A $ cc -mamd64 test.cc && ./a.out $ cc -mamd64 -X /EHa test.cc && ./a.out cl : Command line warning D9025 : overriding '/EHs' with '/EHa' $
The comments suggest that cc -X /EHa
does not conform to POSIX, for example because /EHa
would catch signals. That is not entirely true:
$ cat test.cc #include <signal.h> int main() { try { raise(SIGFPE); } catch (...) { // ignore } } $ cc -mx86 -X /EHa test.cc && ./a.out cl : Command line warning D9025 : overriding '/EHs' with '/EHa' Floating point exception (core dumped)
If I change raise(SIGFPE)
to a division by zero, I do indeed see that the exception handler catches it, but neither POSIX nor C++ requires any particular behaviour for that, so that doesn't affect conformance. It is also not the case that all asynchronous signals are caught: for this program:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void sigint(int signal) {
puts("sigint");
exit(0);
}
int main() {
signal(SIGINT, sigint);
try {
for (;;) ;
} catch (...) {
// ignore
}
}
"sigint" is printed after Ctrl-C, as expected. I don't see a reason for claiming that this implementation fails to meet POSIX requirements.