Reputation: 2061
Is it possible and valide to make a copy of jmp_buf and restore it later? something like
jmp_buf oldEnv = env;
int val = setjmp(env);
.......
env = oldEnv;
I have used memcopy() and sizeof(env), to copy jmp_buf data. This seems to work fine. is this just a coincidence?
Upvotes: 4
Views: 3706
Reputation: 2171
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.)
Upvotes: 1
Reputation: 14603
The only way to do it safely is to implement your own setjmp/longjmp lookalike. Fortunately this is easy to do for most compiler/architecture pairs.
Upvotes: 0
Reputation: 283733
You can do that only if you don't do anything with the jmp_buf
in the interim. Most notably, you can't call setjmp
again, restore the old jmp_buf
content, and use longjmp
to get back to an earlier setjmp
call.
The rule in the C Standard:
The
longjmp
function restores the environment saved by the most recent invocation of thesetjmp
macro in the same invocation of the program with the correspondingjmp_buf
argument.
Because jmp_buf
is "an array type", the call to longjmp
is actually passing a decayed pointer; it is the actual address of the jmp_buf
that the above verbiage concerning "corresponding jmp_buf
argument" references, and not merely its content.
I don't know how the Standard guarantees that you'll return to the context of the most recent setbuf
, if you're been mucking with the contents of the jmp_buf
, so I would treat any modification of the jmp_buf
as making it completely unusable for longjmp
purposes.
If you know something about the internal layout on your particular platform, and you're using jmp_buf
to save processor context to go into a debug log, that sort of thing is fine. But copies can't be used with longjmp
.
Upvotes: 2
Reputation: 3779
According to http://en.cppreference.com/w/c/program/jmp_buf the type of jmp_buf is unspecified. So you don't know what you're going to get when you actually use a jmp_buf
and sizeof might not be returning the actual size of the storage you're memory you'd want to copy. A memcpy and sizeof probably will work, but since you don't know for certain, you might wind up with all sorts of errors.
This also begs the question why you'd want to copy it? The contents of jmp_buf shouldn't be used at all by you. All that you're doing is providing the storage space for the OS to use when setjmp populates env
. Like Ron Popeil said, "Set it and forget it."
Upvotes: 1