There is a lot of inaccurate information in the responses.
Ben is right in that jmp_buf
cannot be reliably saved and restored, and cannot be reliably used with automatic objects with non-trivial destructors. However, if the original question is actually how to save multiple non-local goto points, one solution is to just use a jmp_buf
stack:
jmp_buf env[2];
int env_index = 0;
// first/outer computation
if (setjmp(jmp_buf[env_index++], 0) == 0) {
...
.. call second/inner computation here ..
env_index--;
} else {
...
env_index--;
}
// in second/inner computation
if (setjmp(jmp_buf[env_index++], 0) == 0) {
.. do computation here ..
env_index--;
} else {
.. trap code here ..
env_index--;
}
Regarding setjmp
/longjmp
vs. try
/catch
in C++: the only limitation on using setjmp
/longjmp
is when automatic objects with non-trivial destructors are created but not destroyed between setjmp
and longjmp
- that is, if I do something like setjmp
followed by an auto-variable of std::map<std::string, int> x;
, put a value or two into x
, then longjmp
- the destructor of std::map
is not called to clean up the internal map allocation. But if I have something like this:
// some external library written purely in C
extern "C" do_some_floating_point_computation(params...);
void SIGFPE_handler(...) {
...
.. do longjmp back to wrap_C_Computation_Library here ..
.. after SIGFPE handling ..
}
SomeClass::wrap_C_Computation_Library(...) {
.. set up SIGFPE handler ..
.. setjmp ..
do_some_floating_point_computation(params...);
.. setjmp error handler
.. clean up SIGFPE handler ..
}
there is nothing wrong with using setjmp
in the class method and longjmp
in the SIGFPE handler. (Likewise, trapping some signal across C++ method invocations that don't rely on automatic objects with non-trivial destructors is also ok.)