Setjmp.h
setjmp.h es un encabezado definido en la biblioteca estándar de C para proporcionar "saltos no locales": control de flujo que se desvía de la llamada a subrutina habitual y la secuencia de retorno. Las funciones complementarias setjmp y longjmp proporcionan esta funcionalidad.

Un uso típico de setjmp/longjmp es la implementación de un mecanismo de excepción que utiliza la capacidad de longjmp para restablecer el estado del programa o hilo, incluso a través de múltiples niveles de las llamadas a funciones. Un uso menos común de setjmp es crear una sintaxis similar a corrutinas.

Funciones miembro 

setjmp guarda el contexto actual (Ej., el estado del programa) en algún punto de la ejecución del programa, en una estructura de datos específica de la plataforma (jmp_buf) que puede ser usada, en un punto más lejano de la ejecución del programa, por longjmp para restaurar el estado del programa que fue guardado por setjmp en jmp_buf. Este proceso puede representarse como un "salto" atrás hacia el punto de la ejecución del programa donde setjmp guardo el contexto. El (aparente) valor de retorno de setjmp indica si el control alcanzado el punto de normalidad o de una llamada a  longjmp . Esto lleva a un común idioma: if( setjmp(x) ){/* manejar longjmp(x) */}.

POSIX.1 no especifica si setjmp y longjmp guardan o restauran el conjunto actual de bloqueo de señales — si un programa cuenta con manejo de señales que debería usarlas instrucciones POSIX sigsetjmp/siglongjmp .

Tipos Miembro

Advertencias y limitaciones 
Cuando un "goto no-local" se ejecuta a través de setjmp / longjmp, el "desenrolle de pila" normal no ocurre y por lo tanto, las acciones de limpieza necesarios, tales como el cierre de descriptores de archivos, el vaciado de los búferes, la liberación de la memoria asignada en el heap, etc., no ocurren.

Si la función en la que fue llamada setjmp retorna, ya no es posible utilizar de forma segura longjmp con el objeto jmp_buf correspondiente. Esto es así porque el marco de pila se invalida cuando se devuelve la función. Llamar a longjmp restablece el puntero de pila, que -ya que la función retorna- apuntaría a un marco de pila inexistente y posiblemente sobrescrito o dañado.

Del mismo modo, C99 no requiere que longjmp preserve el marco de pila actual. Esto significa que saltar a una función que sale a través de una llamada a longjmp no está definido. Sin embargo, la mayoría de las implementaciones de longjmp dejan intacto el marco de pila, lo que permite a setjmp y longjmp ser utilizados para saltar hacia atrás y hacia adelante entre dos o más funciones -una característica explotada para la multitarea-.

En comparación con los mecanismos de lenguajes de programación de alto nivel como Python, Java, C + +, C #, e incluso lenguajes pre-C como Algol 60, la técnica de usar setjmp / longjmp para implementar un mecanismo de excepción es engorrosa. Estos lenguajes proporcionan técnicas de manejo de excepciones más potentes, mientras que lenguajes como Scheme, Smalltalk, y Haskell proporcionan construcciones de manejo de continuidad incluso más generales.

Ejemplos de uso

Ejemplo simple 
Este ejemplo muestra la idea básica de setjmp. La función main llama a first, la cual a su vez llama a second. La función "second" salta de vuelta a la función main, omitiendo la ejecución de la instrucción printf de la función "first". 

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

static jmp_buf buf;

void second(void) {
    printf("second\n");         // Impresiones
    longjmp(buf,1);             // salta de nuevo a donde fue llamado setjmp
}

void first(void) {
    second();
    printf("first\n");          // No se Imprime
}

int main() { 
    if ( ! setjmp(buf) ) {
        first();                // Cuando se ejecuta, devuelve 0 setjmp
    } else {                    // cuando salta longjmp, setjmp devuelve 1
        printf("main\n");       // Impresiones
    }

    return 0;
}

Manejo de excepciones 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
 
void first(void);
void second(void);
 
/* This program's output is:
 
calling first
calling second
entering second
second failed with type 3 exception; remapping to type 1.
first failed, exception type 1
 
*/
 
/* 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 *volatile mem_buffer;
 
    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. */
        printf("calling first\n");
        first();
        mem_buffer = malloc(300); /* allocate a resource */
        printf(strcpy((char*) mem_buffer, "first succeeded!")); /* ... this will not happen */
    }
    if (mem_buffer)
        free((void*) mem_buffer); /* carefully deallocate resource */
    return 0;
}
 
void first(void) {
    jmp_buf my_env;
 
    printf("calling second\n");
    memcpy(my_env, exception_env, sizeof(jmp_buf));
    switch (setjmp(exception_env)) {
        case 3:
            /* if we get here there was an exception. */
            printf("second failed with type 3 exception; remapping to type 1.\n");
            exception_type = 1;

        default: /* fall through */
            memcpy(exception_env, my_env, sizeof(jmp_buf)); /* restore exception stack */
            longjmp(exception_env, exception_type); /* continue handling the exception */

        case 0:
            /* normal, desired operation */
            second();
            printf("second succeeded\n");  /* not reached */
    }
    memcpy(exception_env, my_env, sizeof(jmp_buf)); /* restore exception stack */
}
 
void second(void) {
    printf("entering second\n" ); /* reached */
    exception_type = 3;
    longjmp(exception_env, exception_type); /* declare that the program has failed */
    printf("leaving second\n"); /* not reached */
}

Multitarea cooperativa 

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

jmp_buf mainTask, childTask;

void call_with_cushion(void);
void child(void);

int main(void) {
    if (!setjmp(mainTask)) {
        call_with_cushion(); /* child never returns */ /* yield */
    } /* execution resumes after this "}" after first time that child yields */
    for (;;) {
        printf("Parent\n");
        if (!setjmp(mainTask)) {
            longjmp(childTask, 1); /* yield - note that this is undefined under C99 */
        }
    }
}

void call_with_cushion (void) {
    char space[1000]; /* Reserve enough space for main to run */
    space[999] = 1; /* Do not optimize array out of existence */
    child();
}

void child (void) {
    for (;;) {
        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) */
}

Referencias

Enlaces externos 
 
 Exceptions in C with Longjmp and Setjmp

Cabeceras de C
setjmp.h es un encabezado definido en la biblioteca estándar de C para proporcionar " saltos no locales " : control de flujo que se desvía de la llamada a subrutina habitual y la secuencia de retorno . Las funciones complementarias setjmp y longjmp proporcionan esta funcionalidad . Un uso típico de setjmp/longjmp es la implementación de un mecanismo de excepción que utiliza la capacidad de longjmp para restablecer el estado del programa o hilo , incluso a través de múltiples niveles de las llamadas a funciones . Un uso menos común de setjmp es crear una sintaxis similar a corrutinas . Funciones miembro setjmp guarda el contexto actual ( Ej. , el estado del programa ) en algún punto de la ejecución del programa , en una estructura de datos específica de la plataforma ( jmp_buf ) que puede ser usada , en un punto más lejano de la ejecución del programa , por longjmp para restaurar el estado del programa que fue guardado por setjmp en jmp_buf . Este proceso puede representar se como un " salto " atrás hacia el punto de la ejecución del programa donde setjmp guardo el contexto . El ( aparente ) valor de retorno de setjmp indica si el control alcanzado el punto de normalidad o de una llamada a longjmp \ . Esto lleva a un común idioma : if ( setjmp( x ) ) { /* manejar longjmp( x ) */ } . POSIX.1 no especifica si setjmp y longjmp guardan o restauran el conjunto actual de bloqueo de señales — si un programa cuenta con manejo de señales que debería usar las instrucciones POSIX sigsetjmp/siglongjmp \ . Tipos Miembro Advertencias y limitaciones Cuando un " goto no-local " se ejecuta a través de setjmp / longjmp , el " desenrolle de pila " normal no ocurre y por lo tanto , las acciones de limpieza necesarios , tales como el cierre de descriptores de archivos , el vaciado de los búferes , la liberación de la memoria asignada en el heap , etc. , no ocurren . Si la función en la que fue llamada setjmp retorna , ya no es posible utilizar de forma segura longjmp con el objeto jmp_buf correspondiente . Esto es así porque el marco de pila se invalida cuando se devuelve la función . Llamar a longjmp restablece el puntero de pila , que -ya que la función retorna- apuntaría a un marco de pila inexistente y posiblemente sobrescrito o dañado . Del mismo modo , C99 no requiere que longjmp preserve el marco de pila actual . Esto significa que saltar a una función que sale a través de una llamada a longjmp no está definido . Sin embargo , la mayoría de las implementaciones de longjmp dejan intacto el marco de pila , lo que permite a setjmp y longjmp ser utilizados para saltar hacia atrás y hacia adelante entre dos o más funciones -una característica explotada para la multitarea- . En comparación con los mecanismos de lenguajes de programación de alto nivel como Python , Java , C + + , C # , e incluso lenguajes pre-C como Algol la técnica de usar setjmp / longjmp para implementar un mecanismo de excepción es engorrosa . Estos lenguajes proporcionan técnicas de manejo de excepciones más potentes , mientras que lenguajes como Scheme , Smalltalk , y Haskell proporcionan construcciones de manejo de continuidad incluso más generales . Ejemplos de uso Ejemplo simple Este ejemplo muestra la idea básica de setjmp . La función main llama a first , la cual a su vez llama a second . La función " second " salta de vuelta a la función main , omitiendo la ejecución de la instrucción printf de la función " first " . #include <stdio.h> #include <setjmp.h> static jmp_buf buf ; void second( void ) { printf( " second\n " ) ; // Impresiones longjmp( buf,1 ) ; // salta de nuevo a donde fue llamado setjmp } void first( void ) { second ( ) ; printf( " first\n " ) ; // No se Imprime } int main ( ) { if ( ! setjmp( buf ) ) { first ( ) ; // Cuando se ejecuta , devuelvesetjmp } else { // cuando salta longjmp , setjmp devuelve 1 printf( " main\n " ) ; // Impresiones } return } Manejo de excepciones #include <stdio.h> #include <stdlib.h> #include <string.h> #include <setjmp.h> void first( void ) ; void second( void ) ; /* This program's output is : calling first calling second entering second second failed with typeexception ; remapping to type first failed , exception type 1 */ /* 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 *volatile mem_buffer ; 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 . */ printf ( " calling first\n " ) ; first ( ) ; mem_buffer = malloc( 300 ) ; /* allocate a resource */ printf( strcpy ( ( char* ) mem_buffer , " first succeeded ! " ) ) ; /* \ ... this will not happen */ } if ( mem_buffer ) free ( ( void* ) mem_buffer ) ; /* carefully deallocate resource */ return } void first( void ) { jmp_buf my_env ; printf ( " calling second\n " ) ; memcpy( my_env , exception_env , sizeof( jmp_buf ) ) ; switch ( setjmp( exception_env ) ) { case /* if we get here there was an exception . */ printf ( " second failed with typeexception ; remapping to type\n " ) ; exception_type = default : /* fall through */ memcpy( exception_env , my_env , sizeof( jmp_buf ) ) ; /* restore exception stack */ longjmp( exception_env , exception_type ) ; /* continue handling the exception */ case /* normal , desired operation */ second ( ) ; printf ( " second succeeded\n " ) ; /* not reached */ } memcpy( exception_env , my_env , sizeof( jmp_buf ) ) ; /* restore exception stack */ } void second( void ) { printf ( " entering second\n " ) ; /* reached */ exception_type = longjmp( exception_env , exception_type ) ; /* declare that the program has failed */ printf ( " leaving second\n " ) ; /* not reached */ } Multitarea cooperativa #include <setjmp.h> #include <stdio.h> jmp_buf mainTask , childTask ; void call_with_cushion( void ) ; void child( void ) ; int main( void ) { if ( ! setjmp( mainTask ) ) { call_with_cushion ( ) ; /* child never returns */ /* yield */ } /* execution resumes after this " } " after first time that child yields */ for ( ; ; ) { printf( " Parent\n " ) ; if ( ! setjmp( mainTask ) ) { longjmp( childTask , /* yield - note that this is undefined under C99 */ } } } void call_with_cushion ( void ) { char space[ 1000 ] ; /* Reserve enough space for main to run */ space[ 999 ] = /* Do not optimize array out of existence */ child ( ) ; } void child ( void ) { for ( ; ; ) { printf( " Child loop begin\n " ) ; if ( !setjmp( childTask ) ) longjmp( mainTask , /* yield - invalidates childTask in C99 */ printf( " Child loop end\n " ) ; if ( !setjmp( childTask ) ) longjmp( mainTask , /* 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,*/ } Referencias Enlaces externos Exceptions in C with Longjmp and Setjmp Cabeceras de C