Previous Page
Next Page

setjmp

Saves the calling environment as a long jump destination

#include <setjmp.h>
int setjmp ( jmp_buf env  );

The setjmp( ) macro saves the current environment at the time of the call in a buffer specified by its argument. The environment includes the stack, and with it all variables that have automatic storage duration. Like the setjmp( ) macro itself, the argument's type, jmp_buf, is defined in the header file setjmp.h.

A later call to the longjmp( ) function restores the saved environment. As a result, the longjmp( ) function does not return, but instead causes execution to continue as if control had returned from the setjmp( ). However, while the original setjmp( ) call always returns 0, the apparent return value after longjmp( ) is never equal to zero.

Because the execution environment saved may not include other partial expressions, the return value of setjmp( ) must not be used except in simple conditional expressions, or in comparison to an integer constant value. Furthermore, if any variables with automatic storage duration in the function that called setjmp( ) were modified after the setjmp( ) call (and were not declared as volatile), then their values after the longjmp( ) call are indeterminate.

Example

This example shows the complete contents of two source files to illustrate how setjmp( ) and longjmp( ) allow you to escape from a function call.

#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>
#include <errno.h>

double calculate1( double x);      // Functions defined
double calculate2( double x);      // in calculate.c.

jmp_buf jmp_dest;                  // Destination for longjmp( )

int main( )
{
  double x = 0, y1, y2;
  int n = 0;

  puts("--- Demonstrating non-local jumps ---\n");

  switch( setjmp( jmp_dest))     // Jump to here for error handling
  {
  case 0:                        // The original setjmp( ) call
    break;
  case EDOM:                     // Arrived via longjmp( ) call with EDOM
    puts("Domain error. "
         "Negative numbers are not permitted.");
    break;
  case ERANGE:                   // Arrived via longjmp( ) call with ERANGE
    puts("Range error. "
         "The number you entered is too big.");
    break;
  default:                       // We should never arrive here.
    puts("Unknown error.");
    exit( EXIT_FAILURE );
  }

  printf("Enter a number: ");
  do
  {
    if ( (n = scanf("%lf", &x)) < 0)      // Read in a number.
       exit( EXIT_FAILURE );              // Read end of file.
    while ( getchar( ) != '\n')               // Clear the input buffer.
      ;
    if ( n == 0 )
       printf("Invalid entry. Try again: ");
  }while ( n == 0 );

  y1 = calculate1(x);
  y2 = calculate2(x);

  printf("\nResult of Calculation 1: %G\n", y1);
  printf(  "Result of Calculation 2: %G\n", y2);

  return 0;
}

// calculate.c: Perform some calculations.
// Functions: calculate1( ), calculate2( ).
#include <math.h>
#include <setjmp.h>
#include <errno.h>

extern jmp_buf jmp_dest;                  // Destination for longjmp( )

double calculate1( double x)
{
  if ( x < 0)
    longjmp( jmp_dest, EDOM);        // Domain error
  else
    return sqrt(x);
}

double calculate2( double x)
{
  double y = exp(x);
  if ( y == HUGE_VAL)
    longjmp( jmp_dest, ERANGE);      // Range error
  else
    return y;
}

See Also

longjmp( )


Previous Page
Next Page