Herramientas de usuario

Herramientas del sitio


setjmp

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anteriorRevisión previa
Próxima revisión
Revisión previa
setjmp [2012/08/23 04:31] lmateusetjmp [2016/11/22 12:56] (actual) – [Manejo de errores] lmateu
Línea 6: Línea 6:
 de una función a otra función más abajo en la pila de llamadas de una función a otra función más abajo en la pila de llamadas
 a funciones. a funciones.
 +
 +Por ejemplo, si se busca un dato específico en un árbol binario no ordenado, esta búsqueda es recursiva.  Cuando encontramos el dato buscado no gustaría terminar de inmediato la búsqueda volviendo a la primera de las llamadas.
 +Sin excepciones esto no se puede hacer: hay que retornar de cada una de las llamadas recursivas.  Para eso existe
 +en C setjmp y longjmp.  Estas funciones permiten tomar un //atajo// para retornar directamente a un punto específico
 +de la ejecución.
 +
 +Esta es la solución para el caso de una busqueda recursiva en un árbol binario no ordenado.
  
 <code> <code>
Línea 54: Línea 61:
 retorno, el valor es lo que se especificó como argumento en el longjmp y por eso es importante retorno, el valor es lo que se especificó como argumento en el longjmp y por eso es importante
 que sea distinto de 0 para poder distinguirlo del primer retorno. que sea distinto de 0 para poder distinguirlo del primer retorno.
 +
 +==== Manejo de errores ====
 +
 +La funciones setjmp y longjmp se usan sobretodo para manejar situaciones de error, al igual que las excepciones.  Por ejemplo un programa puede tener un ciclo en donde se leen comandos de la entrada estándar y se procesan.  Si el programa detecta un error al final de una larga cadena de llamadas de funciones, no es necesario manejar el error en todas las funciones.  Se puede invocar longjmp para retornar directamente al ciclo de lectura de comandos.  Esto sería algo así:
 +
 +<code>
 +  jmp_buf env;
 +  int main() {
 +    for(;;) {
 +      if (setjmp(env)==0) {
 +        char buf[80];
 +        int leidos= fread(buf, 1, 80, stdin);
 +        if (leidos==0)
 +          break;
 +        procesar(buf, leidos);
 +      }
 +    }
 +    return 0;
 +  }
 +  
 +  void procesar(char *buf, int n) { ... f(); ... }
 +  void f() { ... g(); ... }
 +  void g() { ... h(); ... }
 +  
 +  void h() {
 +    ...
 +    if (x>=1000) {
 +      fprintf(stderr, "el parámetro x=%d es demasiado grande\n", x);
 +      longjmp(env, 1);
 +    }
 +    ...
 +  }
 +</code>
 +
 +De esta forma el programa puede seguir procesando comandos en vez de terminar abruptamente el programa o alternativamente manejar la condición de error en g, h, procesar, etc.
 +
 +El inconveniente de este enfoque es que si la función f pidió memoria o abrió un archivo que tenía que liberar o cerrar al retornar, si ocurre el error la memoria y el archivo abierto se transformarán en goteras.  Esto en Java se puede resolver usando try/finally en f, cerrando por ejemplo el archivo en el bloque finally.  Java asegura que esas instrucciones se ejecutarán en caso de una excepción.  Lamentablemente C no posee algo parecido.
 +
 +==== Discusión ====
  
 Hay que reconocer que el funcionamiento de setjmp y longjmp es Hay que reconocer que el funcionamiento de setjmp y longjmp es
setjmp.1345696267.txt.gz · Última modificación: 2012/08/23 04:31 por lmateu