GetWiki
setjmp.h
ARTICLE SUBJECTS
being →
database →
ethics →
fiction →
history →
internet →
language →
linux →
logic →
method →
news →
policy →
purpose →
religion →
science →
software →
truth →
unix →
wiki →
ARTICLE TYPES
essay →
feed →
help →
system →
wiki →
ARTICLE ORIGINS
critical →
forked →
imported →
original →
setjmp.h
please note:
- the content below is remote from Wikipedia
- it has been imported raw for GetWiki
{{Short description|Header file for C programs}}{{Lowercase title}}{{More citations needed|date=December 2016}}{{C standard library}}setjmp.h is a header defined in the C standard library to provide "non-local jumps": control flow that deviates from the usual subroutine call and return sequence. The complementary functions setjmp and longjmp provide this functionality.A typical use of setjmp/longjmp is implementation of an exception mechanism that exploits the ability of longjmp to reestablish program or thread state, even across multiple levels of function calls. A less common use of setjmp is to create syntax similar to coroutines.- the content below is remote from Wikipedia
- it has been imported raw for GetWiki
| An array type, such as struct __jmp_buf_tag[1],This is the type used by the GNU C Library, version 2.7 suitable for holding the information needed to restore a calling environment. |
Caveats and limitations
When a "non-local goto" is executed via setjmp/longjmp in C++, normal "stack unwinding" does not occur. Therefore, any required cleanup actions will not occur either. This could include closing file descriptors, flushing buffers, or freeing heap-allocated memory.If the function in which setjmp was called returns, it is no longer possible to safely use longjmp with the corresponding jmp_buf object. This is because the stack frame is invalidated when the function returns. Calling longjmp restores the stack pointer, whichâbecause the function returnedâwould point to a non-existent and potentially overwritten or corrupted stack frame.CS360 Lecture Notes â Setjmp and Longjmpsetjmp(3) {{webarchive|url=https://web.archive.org/web/20090726081425weblink |date=2009-07-26 }}Similarly, C99 does not require that longjmp preserve the current stack frame. This means that jumping into a function which was exited via a call to longjmp is undefined.ISO/IEC 9899:1999, 2005, 7.13.2.1:2 and footnote 211Example usage
Simple example
The example below shows the basic idea of setjmp. There, main() calls first(), which in turn calls second(). Then, second() jumps back into main(), skipping first()'s call of printf().- include
- include
printf("secondn"); // prints
longjmp(buf, 1); // jumps back to where setjmp was called - making setjmp now return 1
}void first() {
longjmp(buf, 1); // jumps back to where setjmp was called - making setjmp now return 1
second();
printf("firstn"); // does not print
}int main() {
printf("firstn"); // does not print
if (!setjmp(buf))
first(); // when executed, setjmp returned 0
else // when longjmp jumps back, setjmp returns 1
printf("mainn"); // prints
first(); // when executed, setjmp returned 0
else // when longjmp jumps back, setjmp returns 1
printf("mainn"); // prints
return 0;
}When executed, the above program will output:secondmainNotice that although the first() subroutine gets called, "first" is never printed. "main" gets printed as the conditional statement if (!setjmp(buf)) is executed a second time.Exception handling
In this example, setjmp is used to bracket exception handling, like try in some other languages. The call to longjmp is analogous to a throw statement, allowing an exception to return an error status directly to the setjmp. The following code adheres to the 1999 ISO C standard and Single UNIX Specification by invoking setjmp in a limited range of contexts:{{man|sh|setjmp|SUS|set jump point for a non-local goto}}- As the condition to an if, switch or iteration statement
- As above in conjunction with a single ! or comparison with an integer constant
- As a statement (with the return value unused)
- include
- include
- include
- include
* it anywhere within this translation unit. */
static jmp_buf exception_env;static int exception_type;int main(void) {
char* volatile mem_buffer = NULL;
if (setjmp(exception_env)) {
// if we get here there was an exception
printf("first failed, exception type: %dn", exception_type);
} else {
// Run code that may signal failure via longjmp.
puts("calling first");
first();
// if we get here there was an exception
printf("first failed, exception type: %dn", exception_type);
} else {
// Run code that may signal failure via longjmp.
puts("calling first");
first();
mem_buffer = malloc(300); // allocate a resource
printf("%sn", strcpy(mem_buffer, "first succeeded")); // not reached
}
printf("%sn", strcpy(mem_buffer, "first succeeded")); // not reached
}
free(mem_buffer); // NULL can be passed to free, no operation is performed
return 0;
}static void first() {
jmp_buf my_env;
puts("entering first"); // reached
memcpy(my_env, exception_env, sizeof my_env);
switch (setjmp(exception_env)) {
case 3: // if we get here there was an exception.
puts("second failed, exception type: 3; remapping to type 1");
exception_type = 1;
case 3: // if we get here there was an exception.
puts("second failed, exception type: 3; remapping to type 1");
exception_type = 1;
default: // fall through
memcpy(exception_env, my_env, sizeof exception_env); // restore exception stack
longjmp(exception_env, exception_type); // continue handling the exception
memcpy(exception_env, my_env, sizeof exception_env); // restore exception stack
longjmp(exception_env, exception_type); // continue handling the exception
case 0: // normal, desired operation
puts("calling second"); // reached
second();
puts("second succeeded"); // not reached
}
puts("calling second"); // reached
second();
puts("second succeeded"); // not reached
}
memcpy(exception_env, my_env, sizeof exception_env); // restore exception stack
puts("leaving first"); // never reached
}static void second() {
puts("entering second" ); // reached
exception_type = 3;
longjmp(exception_env, exception_type); // declare that the program has failed
longjmp(exception_env, exception_type); // declare that the program has failed
puts("leaving second"); // not reached
}This program's output is:calling firstentering firstcalling secondentering secondsecond failed, exception type: 3; remapping to type 1first failed, exception type: 1Cooperative multitasking
C99 provides that longjmp is guaranteed to work only when the destination is a calling function, i.e., that the destination scope is guaranteed to be intact. Jumping to a function that has already terminated by return or longjmp is undefined. However, most implementations of longjmp do not specifically destroy local variables when performing the jump. Since the context survives until its local variables are erased, it could actually be restored by setjmp. In many environments (such as Really Simple Threads and TinyTimbers), idioms such as if(!setjmp(child_env)) longjmp(caller_env); can allow a called function to effectively pause-and-resume at a setjmp.This is exploited by thread libraries to provide cooperative multitasking facilities without using setcontext or other fiber facilities.Considering that setjmp to a child function will generally work unless sabotaged, and setcontext, as part of POSIX, is not required to be provided by C implementations, this mechanism may be portable where the setcontext alternative fails.Since no exception will be generated upon overflow of one of the multiple stacks in such a mechanism, it is essential to overestimate the space required for each context, including the one containing main() and including space for any signal handlers that might interrupt regular execution. Exceeding the allocated space will corrupt the other contexts, usually with the outermost functions first. Unfortunately, systems requiring this kind of programming strategy are often also small ones with limited resources.- include
- include
if (!setjmp(mainTask)) {
call_with_cushion(); // child never returns, yield
} // execution resumes after this "}" after first time that child yields
call_with_cushion(); // child never returns, yield
} // execution resumes after this "}" after first time that child yields
while (1) {
printf("Parentn");
if (!setjmp(mainTask))
longjmp(childTask, 1); // yield - note that this is undefined under C99
}
}void call_with_cushion() {
printf("Parentn");
if (!setjmp(mainTask))
longjmp(childTask, 1); // yield - note that this is undefined under C99
}
char space[1000]; // Reserve enough space for main to run
space[999] = 1; // Do not optimize array out of existence
child();
}void child() {
space[999] = 1; // Do not optimize array out of existence
child();
while (1) {
printf("Child loop beginn");
if (!setjmp(childTask))
longjmp(mainTask, 1); // yield - invalidates childTask in C99
printf("Child loop beginn");
if (!setjmp(childTask))
longjmp(mainTask, 1); // yield - invalidates childTask in C99
printf("Child loop endn");
if (!setjmp(childTask))
longjmp(mainTask, 1); // yield - invalidates childTask in C99
}
longjmp(mainTask, 1); // yield - invalidates childTask in C99
}
/* Don't return. Instead we should set a flag to indicate that main()
should stop yielding to us and then longjmp(mainTask, 1) */
}should stop yielding to us and then longjmp(mainTask, 1) */
References
{{Reflist}}Further reading
- WEB, Nidito, Francesco, July 2, 2016, Exceptions in C with Longjmp and Setjmp,weblink Groups.Di.Unipi.it, 2024-01-02,
External links
- {{man|sh|setjmp|SUS|set jump point for a non-local goto}}
- is there sigsetjmp/siglongjmp (again) (about this functions in mingw/MSYS)
- content above as imported from Wikipedia
- "setjmp.h" does not exist on GetWiki (yet)
- time: 3:09pm EDT - Wed, May 15 2024
- "setjmp.h" does not exist on GetWiki (yet)
- time: 3:09pm EDT - Wed, May 15 2024
[ this remote article is provided by Wikipedia ]
LATEST EDITS [ see all ]
GETWIKI 23 MAY 2022
The Illusion of Choice
Culture
Culture
GETWIKI 09 JUL 2019
Eastern Philosophy
History of Philosophy
History of Philosophy
GETWIKI 09 MAY 2016
GetMeta:About
GetWiki
GetWiki
GETWIKI 18 OCT 2015
M.R.M. Parrott
Biographies
Biographies
GETWIKI 20 AUG 2014
GetMeta:News
GetWiki
GetWiki
© 2024 M.R.M. PARROTT | ALL RIGHTS RESERVED