fbpx
Wikipedia

setjmp.h

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.

Member functions edit

int setjmp(jmp_buf env) 
Sets up the local jmp_buf buffer and initializes it for the jump. This routine[1] saves the program's calling environment in the environment buffer specified by the env argument for later use by longjmp. If the return is from a direct invocation, setjmp returns 0. If the return is from a call to longjmp, setjmp returns a nonzero value.
void longjmp(jmp_buf env, int value) 
Restores the context of the environment buffer env that was saved by invocation of the setjmp routine[1] in the same invocation of the program. Invoking longjmp from a nested signal handler is undefined. The value specified by value is passed from longjmp to setjmp. After longjmp is completed, program execution continues as if the corresponding invocation of setjmp had just returned. If the value passed to longjmp is 0, setjmp will behave as if it had returned 1; otherwise, it will behave as if it had returned value.

setjmp saves the current environment (the program state), at some point of program execution, into a platform-specific data structure (jmp_buf) that can be used at some later point of program execution by longjmp to restore the program state to that saved by setjmp into jmp_buf. This process can be imagined to be a "jump" back to the point of program execution where setjmp saved the environment. The (apparent) return value from setjmp indicates whether control reached that point normally (zero) or from a call to longjmp (nonzero). This leads to a common idiom: if( setjmp(x) ){/* handle longjmp(x) */}.

POSIX.1 does not specify whether setjmp and longjmp save and restore the current set of blocked signals; if a program employs signal handling it should use POSIX's sigsetjmp/siglongjmp.

Member types edit

jmp_buf An array type, such as struct __jmp_buf_tag[1],[2] suitable for holding the information needed to restore a calling environment.

The C99 Rationale describes jmp_buf as being an array type for backward compatibility; existing code refers to jmp_buf storage locations by name (without the & address-of operator), which is only possible for array types.[3]

Caveats and limitations edit

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.[4][5]

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.[6] However, most implementations of longjmp leave the stack frame intact, allowing setjmp and longjmp to be used to jump back-and-forth between two or more functions—a feature exploited for multitasking.

Example usage edit

Simple example edit

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 <stdio.h> #include <setjmp.h> static jmp_buf buf; void second() {  printf("second\n"); // prints  longjmp(buf,1); // jumps back to where setjmp was called - making setjmp now return 1 } void first() {  second();  printf("first\n"); // does not print } int main() {  if (!setjmp(buf))  first(); // when executed, setjmp returned 0  else // when longjmp jumps back, setjmp returns 1  printf("main\n"); // prints  return 0; } 

When executed, the above program will output:

second main 

Notice 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 edit

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:[7]

  • 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)

Following these rules can make it easier for the implementation to create the environment buffer, which can be a sensitive operation.[3] More general use of setjmp can cause undefined behaviour, such as corruption of local variables; conforming compilers and environments are not required to protect or even warn against such usage. However, slightly more sophisticated idioms such as switch ((exception_type = setjmp(env))) { } are common in literature and practice, and remain relatively portable. A simple conforming methodology is presented below, where an additional variable is maintained along with the state buffer. This variable could be elaborated into a structure incorporating the buffer itself.

In a more modern-looking example, the usual "try" block would be implemented as a setjmp (with some preparation code for multilevel jumps, as seen in first), the "throw" as longjmp with the optional parameter as the exception, and the "catch" as the "else" block under "try".

#include <setjmp.h> #include <stdio.h> #include <stdlib.h> #include <string.h> static void first(); static void second(); /* Use a file scoped static variable for the exception stack so we can access  * 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: %d\n", exception_type);  } else {  // Run code that may signal failure via longjmp.  puts("calling first");  first();  mem_buffer = malloc(300); // allocate a resource  printf("%s\n", 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;  default: // fall through  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  }  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  puts("leaving second"); // not reached } 

This program's output is:

calling first entering first calling second entering second second failed, exception type: 3; remapping to type 1 first failed, exception type: 1 

Cooperative multitasking edit

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.[6] 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 <setjmp.h> #include <stdio.h> jmp_buf mainTask, childTask; void call_with_cushion(); void child(); int main() {  if (!setjmp(mainTask)) {  call_with_cushion(); // child never returns, yield  } // execution resumes after this "}" after first time that child yields  while (1) {  printf("Parent\n");    if (!setjmp(mainTask))  longjmp(childTask, 1); // yield - note that this is undefined under C99  } } void call_with_cushion() {  char space[1000]; // Reserve enough space for main to run  space[999] = 1; // Do not optimize array out of existence  child(); } void child() {  while (1) {  printf("Child loop begin\n");    if (!setjmp(childTask))  longjmp(mainTask, 1); // yield - invalidates childTask in C99  printf("Child loop end\n");  if (!setjmp(childTask))  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) */ } 

References edit

  1. ^ a b ISO C states that setjmp must be implemented as a macro, but POSIX explicitly states that it is undefined whether setjmp is a macro or a function.
  2. ^ This is the type used by the GNU C Library, version 2.7
  3. ^ a b C99 Rationale, version 5.10, April 2003, section 7.13
  4. ^ CS360 Lecture Notes — Setjmp and Longjmp
  5. ^ setjmp(3) 2009-07-26 at the Wayback Machine
  6. ^ a b ISO/IEC 9899:1999, 2005, 7.13.2.1:2 and footnote 211
  7. ^ setjmp: set jump point for a non-local goto – System Interfaces Reference, The Single UNIX Specification, Version 4 from The Open Group

External links edit

setjmp, this, article, needs, additional, citations, verification, please, help, improve, this, article, adding, citations, reliable, sources, unsourced, material, challenged, removed, find, sources, setjmp, news, newspapers, books, scholar, jstor, december, 2. This article needs additional citations for verification Please help improve this article by adding citations to reliable sources Unsourced material may be challenged and removed Find sources Setjmp h news newspapers books scholar JSTOR December 2016 Learn how and when to remove this template message 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 Contents 1 Member functions 2 Member types 3 Caveats and limitations 4 Example usage 4 1 Simple example 4 2 Exception handling 4 3 Cooperative multitasking 5 References 6 External linksMember functions editint setjmp jmp buf env Sets up the local jmp buf buffer and initializes it for the jump This routine 1 saves the program s calling environment in the environment buffer specified by the env argument for later use by longjmp If the return is from a direct invocation setjmp returns 0 If the return is from a call to longjmp setjmp returns a nonzero value void longjmp jmp buf env int value Restores the context of the environment buffer env that was saved by invocation of the setjmp routine 1 in the same invocation of the program Invoking longjmp from a nested signal handler is undefined The value specified by value is passed from longjmp to setjmp After longjmp is completed program execution continues as if the corresponding invocation of setjmp had just returned If the value passed to longjmp is 0 setjmp will behave as if it had returned 1 otherwise it will behave as if it had returned value setjmp saves the current environment the program state at some point of program execution into a platform specific data structure jmp buf that can be used at some later point of program execution by longjmp to restore the program state to that saved by setjmp into jmp buf This process can be imagined to be a jump back to the point of program execution where setjmp saved the environment The apparent return value from setjmp indicates whether control reached that point normally zero or from a call to longjmp nonzero This leads to a common idiom span class k if span span class p span span class w span span class n setjmp span span class p span span class n x span span class p span span class w span span class p span span class cm handle longjmp x span span class p span POSIX 1 does not specify whether setjmp and longjmp save and restore the current set of blocked signals if a program employs signal handling it should use POSIX s sigsetjmp siglongjmp Member types editjmp buf An array type such as struct jmp buf tag 1 2 suitable for holding the information needed to restore a calling environment The C99 Rationale describes jmp buf as being an array type for backward compatibility existing code refers to jmp buf storage locations by name without the amp address of operator which is only possible for array types 3 Caveats and limitations editWhen 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 4 5 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 6 However most implementations of longjmp leave the stack frame intact allowing setjmp and longjmp to be used to jump back and forth between two or more functions a feature exploited for multitasking Example usage editSimple example edit 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 lt stdio h gt include lt setjmp h gt static jmp buf buf void second printf second n prints longjmp buf 1 jumps back to where setjmp was called making setjmp now return 1 void first second printf first n does not print int main if setjmp buf first when executed setjmp returned 0 else when longjmp jumps back setjmp returns 1 printf main n prints return 0 When executed the above program will output second main Notice 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 edit 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 7 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 Following these rules can make it easier for the implementation to create the environment buffer which can be a sensitive operation 3 More general use of setjmp can cause undefined behaviour such as corruption of local variables conforming compilers and environments are not required to protect or even warn against such usage However slightly more sophisticated idioms such as switch exception type setjmp env are common in literature and practice and remain relatively portable A simple conforming methodology is presented below where an additional variable is maintained along with the state buffer This variable could be elaborated into a structure incorporating the buffer itself In a more modern looking example the usual try block would be implemented as a setjmp with some preparation code for multilevel jumps as seen in first the throw as longjmp with the optional parameter as the exception and the catch as the else block under try include lt setjmp h gt include lt stdio h gt include lt stdlib h gt include lt string h gt static void first static void second Use a file scoped static variable for the exception stack so we can access 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 d n exception type else Run code that may signal failure via longjmp puts calling first first mem buffer malloc 300 allocate a resource printf s n 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 default fall through 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 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 puts leaving second not reached This program s output is calling first entering first calling second entering second second failed exception type 3 remapping to type 1 first failed exception type 1 Cooperative multitasking edit 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 6 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 a href Setcontext html title Setcontext setcontext a 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 lt setjmp h gt include lt stdio h gt jmp buf mainTask childTask void call with cushion void child int main if setjmp mainTask call with cushion child never returns yield execution resumes after this after first time that child yields while 1 printf Parent n if setjmp mainTask longjmp childTask 1 yield note that this is undefined under C99 void call with cushion char space 1000 Reserve enough space for main to run space 999 1 Do not optimize array out of existence child void child while 1 printf Child loop begin n if setjmp childTask longjmp mainTask 1 yield invalidates childTask in C99 printf Child loop end n if setjmp childTask 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 References edit a b ISO C states that setjmp must be implemented as a macro but POSIX explicitly states that it is undefined whether setjmp is a macro or a function This is the type used by the GNU C Library version 2 7 a b C99 Rationale version 5 10 April 2003 section 7 13 CS360 Lecture Notes Setjmp and Longjmp setjmp 3 Archived 2009 07 26 at the Wayback Machine a b ISO IEC 9899 1999 2005 7 13 2 1 2 and footnote 211 setjmp set jump point for a non local goto System Interfaces Reference The Single UNIX Specification Version 4 from The Open GroupExternal links edit nbsp Computer programming portalsetjmp set jump point for a non local goto System Interfaces Reference The Single UNIX Specification Version 4 from The Open Group Exceptions in C with Longjmp and Setjmp is there sigsetjmp siglongjmp again about this functions in mingw MSYS Retrieved from https en wikipedia org w index php title Setjmp h amp oldid 1146072046, wikipedia, wiki, book, books, library,

article

, read, download, free, free download, mp3, video, mp4, 3gp, jpg, jpeg, gif, png, picture, music, song, movie, book, game, games.