Herramientas de usuario

Herramientas del sitio


setjmp

¡Esta es una revisión vieja del documento!


setjmp/longjmp

C no posee excepciones como Java (o C++). Un efecto parecido se puede lograr con setjmp y longjmp. La primera función marca un lugar de retorno. La segunda función realiza un salto de una función a otra función más abajo en la pila de llamadas a funciones.

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

  typedef struct node {
    int x;
    struct node *left, *right;
  } Node;

  void search2(Node *t, int y, jmp_buf env) {
    if (t==NULL)
      return;
    if (t->x==y)
      longjmp(env, 1); /* salto a la función search */
    search2(t->left, y, env);
    search2(t->right, y, env);
  }

  int search(Node *t, int y) {
    jmp_buf env;
    int found;
    if (setjmp(env)==0) { /* marca el destino del salto con longjmp */
      search2(t, y, env);
      found= 0;
    }
    else {
      found= 1;
    }
    return found;
  }

  Node n1= { 1, NULL, NULL };
  Node n2= { 2, NULL, NULL };
  Node r= { 3, &n1, &n2 };

  int main(int argc, char **argv) {
    printf("%d\n", search(&r, atoi(argv[1])));
    return 0;
  }

Es importante que la función destinataria del salto no haya retornado aún. De otra forma los efectos son impredecibles. Observe que setjmp retorna 2 veces: el primer retorno ocurre la primera vez que se invoca stjmp para marcar el destino del salto, el segundo es cuando se invoca longjmp. El valor retornado en el primer retorno es siempre 0. En el segundo retorno, el valor es lo que se especificó como parámetro en el longjmp y por eso es importante que sea distinto de 0 para poder distinguirlo del primer retorno.

Hay que reconocer que el funcionamiento de setjmp y longjmp es de lo más retorcido del lenguaje C. De hecho estas funciones tienen que programarse en assembler ya que su funcionalidad no se puede expresar en C.

Uno de los principios de diseño de C es la minimización de las abstracciones del lenguaje. Si una funcionalidad del lenguaje se puede lograr con funciones, entonces ella se realiza con funciones de biblioteca, sin añadir una nueva abstracción al lenguaje. Esto explica la ausencia de la instrucción try/catch/finally de Java en C. Por supuesto, esto es discutible desde el punto de vista de la robustez, ya que el uso de setjmp y longjmp en C conducen a errores que son difíciles de diagnosticar.

setjmp.1345693102.txt.gz · Última modificación: 2012/08/23 03:38 por lmateu