Setjmp.h

Setjmp.h

.

Plantilla:Lowercase 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 co-rutinas.

Plantilla:Biblioteca Estandar C

Contenido

Funciones miembro

int setjmp(jmp_buf env) Establece el buffer jmp_buf local y lo inicializa para el salto. Esta rutina[1] guarda el contexto de la llamada del programa en el búfer de contexto especificado por el argumento env para su uso posterior por longjmp. Si el retorno es de una invocación directa, setjmp devuelve 0. Si el retorno es de una llamada a longjmp, setjmp devuelve un valor distinto de cero.
void longjmp(jmp_buf env, int value) Restaura el contexto del buffer de entorno env que se salvó por invocación de la rutina[1] en la misma invocación del programa. Invocando longjmp desde un manejador de señales anidado no-definido. El valor especificado por valor es pasado desde longjmp a setjmp. Después de que longjmp se completa, la ejecución del programa continúa como si la invocación correspondiente de setjmp acabara de regresar. Si el valor pasado a longjmp es 0, setjmp se comportará como si hubiera devuelto 1;, de lo contrario, se comportará como si hubiera devuelto un valor.

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" atras 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 [[lenguaje de programació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 deberia usarlas instrucciones POSIX sigsetjmp/siglongjmp .

Tipos Miembro

jmp_buf Un tipo de array, como struct __jmp_buf_tag[1],[2] apropiado para manejar la información necesaria para restaurar el contexto desde una llamada a sistema.

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

Advertencias y limitaciones

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

Si la función en la que fue llamada setjmp regresa, 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 devuelve-apuntaría a una pila no existe y posiblemente sobrescribir / dañado frame.4 5

Del mismo modo, C99 no requiere que longjmp preservar el marco de pila actual. Esto significa que saltar a una función que se sale a través de una llamada a longjmp es undefined.6 Sin embargo, la mayoría de las implementaciones de longjmp dejar intacto el marco de pila, lo que permite setjmp y longjmp que se utiliza 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 pre-C lenguajes como Algol 60, la técnica del uso de setjmp / longjmp para implementar un mecanismo de excepción es aburrida. Estos lenguajes proporcionan las técnicas de manejo de excepción más potente, mientras que lenguas como el esquema, Smalltalk, y Haskell proporcionar más generales de manipulación de continuación construcciones.

Ejemplos de uso

Ejemplo simple

Este ejemplo muestra la idea básica de setjmp. Main calls first, which in turn calls second. The "second" function jumps back into main, skipping "first"'s print statement.

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

Manejo de excepciones

En este ejemplo, setjmp is used to bracket exception handling, like 1999 ISO C standard and Single UNIX Specification by invoking setjmp in a limited range of contexts:[4]

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

#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

C99 provee que 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.[5] 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. Whereas setcontext is a library service which can create an execution context in heap-allocated memory and can support other services such as buffer overflow protection[cita requerida], abuse of setjmp is implemented by the programmer, who may reserve memory on the stack and fail to notify the library or operating system of the new operating context. On the other hand, a library's implementation of setcontext may internally use setjmp in a fashion similar to this example to save and restore a context, after it has been initialised somehow.

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);
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) */
}

Véase también

  • setcontext
  • continuation

Referencias

  1. a b ISO C establece que setjmp</ code> debe ser implementado como una macro, pero POSIX establece explícitamente que no está definido si setjmp</ code> es una macro o una función.
  2. Este es el tipo usado por la Biblioteca GNU C, version 2.7
  3. a b C99 Rationale, version 5.10, April 2003, section 7.13
  4. Plantilla:Man
  5. Error en la cita: El elemento <ref> no es válido; pues no hay una referencia con texto llamada ISO.2FIEC_9899:1999

Enalces Externos


Wikimedia foundation. 2010.

Игры ⚽ Поможем сделать НИР

Mira otros diccionarios:

  • Setjmp.h — is a header defined in the C standard library to provide non local jumps (control flow) outside of the normal function call and return sequence. The paired functions setjmp and longjmp provide this functionality through first saving the… …   Wikipedia

  • Setjmp — Связать? setjmp  функция в языках программирования Си (язык программирования) и C++. Сохранаяет текущий контекст выполнения программы для обеспечения дальнейшего восстановления. Содержание …   Википедия

  • setjmp.h — C Standard Library Data types Character classification Strings Mathematics File input/output Date/time Localization …   Wikipedia

  • setjmp.h — Стандартная библиотека языка программирования С assert.h complex.h ctype.h errno.h fenv.h float.h inttypes.h iso646.h limits.h locale.h math.h setjmp.h signal.h stdarg.h stdbool.h stddef.h …   Википедия

  • Setjmp (функция) — setjmp сохранаяет текущий контекст выполнения программы для обеспечения дальнейшего восстановления Содержание 1 Синтаксис 2 Описание 3 Возвращаемое значение 4 См. также …   Википедия

  • Longjmp — Эту страницу предлагается объединить с setjmp.h. Пояснение причин и обсуждение на странице Википедия:К объединению/10 октября 2011. Обсуждение длится одну неделю (или дольше, если оно идёт медленно). Дата начала …   Википедия

  • Coroutine — Coroutines are computer program components that generalize subroutines to allow multiple entry points for suspending and resuming execution at certain locations. Coroutines are well suited for implementing more familiar program components such as …   Wikipedia

  • C standard library — The C Standard Library consists of a set of sections of the ANSI C standard in the programming language C. They describe a collection of headers and library routines used to implement common operations such as input/output[1] and string handling …   Wikipedia

  • Funciones de la biblioteca estándar de C — Anexo:Funciones de la biblioteca estándar de C Saltar a navegación, búsqueda El propósito de este artículo es proporcionar un listado alfabético de todas las funciones de la biblioteca estándar de C, y unas pocas funciones no estándar. Contenido… …   Wikipedia Español

  • Стандартная библиотека языка Си — Стандартная библиотека языка программирования С assert.h complex.h ctype.h errno.h fenv.h float.h inttypes.h iso646.h limits.h locale.h math.h setjmp.h signal.h stdarg.h stdbool.h stddef.h …   Википедия

Compartir el artículo y extractos

Link directo
Do a right-click on the link above
and select “Copy Link”