setjmp/longjmp y variables locales

3 minutos de lectura

Mis preguntas apuntan al comportamiento de setjmp/longjmp con respecto a las variables locales.

Código de ejemplo:

jmp_buf env;


void abc()
{
  int error;

  ... 
  if(error)
    longjmp(env);
}


void xyz() {
  int v1;           // non-volatile; changed between setjmp and longjmp
  int v2;           // non-volatile; not changed between setjmp and longjmp
  volatile int v3;  // volatile;     changed between setjmp and longjmp
  volatile int v4;  // volatile;     not changed between setjmp and longjmp 

  ...

  if(setjmp(env)) {
    // error handling
    ...
    return;
  }

  v1++; // change v1
  v3++; // change v3

  abc();
}


int main(...) {
  xyz();
}

La documentación de setjmp/longjmp dice:

“Todos los objetos accesibles tienen valores a partir del momento en que se llamó a longjmp(), excepto que los valores de los objetos de duración de almacenamiento automático que son locales a la función que contiene la invocación del setjmp() correspondiente que no tienen un tipo calificado como volátil y que se modifican entre la invocación de setjmp() y la llamada de longjmp() son indeterminadas”.

Veo las siguientes dos posibles interpretaciones:

interpretación1:

Las variables locales se restauran, excepto aquellas que son ambas.

  • no volátil y
  • cambió

interpretación2:

Las variables locales se restauran, excepto

  • aquellos que no son volátiles y
  • los que estan cambiados

De acuerdo con la interpretación 1, después de longjmp, solo v1 no está definido. v2, v3, v4 están definidos. Según la interpretación 2, después de longjmp, solo se define v4. v1, v2, v3 no están definidos.

¿Cuál es la correcta?

Por cierto: necesito una respuesta general (“portátil”) que sea válida para todos los compiladores, es decir, probar con un compilador en particular no ayuda.

  • Nota de implementación: las variables que se modifican y no son volátiles pueden ser como eran en el momento de longjmp, o pueden restaurarse a lo que eran en el momento de setjmp, según la generación de código. Por lo tanto, ‘indeterminado’. Entonces, si fueran no cambiado, estos dos valores son los mismos y es por eso que las variables sin cambios son seguras.

    – grego

    13 de abril de 2012 a las 21:27

avatar de usuario
Será

setjmp/longjmp se implementa guardando los registros (incluidos los punteros de pila y de código, etc.) cuando se pasa por primera vez, y restaurándolos al saltar.

Variables automáticas (también conocidas como “locales”, asignadas por pila) que no son “volátiles” puede almacenarse en registros en lugar de en la pila.

En estas circunstancias, longjmp restaurará estas variables de registros a su valor en el punto en que se llamó por primera vez a setjmp().

Además, un compilador particularmente inteligente podría evitar las variables que se pueden inferir del estado de otra variable y calcularlas a pedido.

Sin embargo, si la variable es automática pero no se le ha asignado un registro, se puede cambiar por código entre setjmp y longjmp.

Volatile le dice explícitamente al compilador que no almacene la variable en un registro.

Entonces, a menos que diga explícitamente que una variable es volátil, si cambió la variable entre setjmp/longjmp, su valor dependerá de las elecciones que haga el compilador y, por lo tanto, no es nada en lo que deba confiar (‘indeterminado’).

  • Y supongo que por el contrario, las variables automáticas declaradas como ‘registro’ puede almacenarse en registros, pero el compilador podría ignorar la sugerencia, por lo que esto tampoco puede garantizar que se restaurarán.

    – Miguel

    17/04/2015 a las 17:33

  • @Michael En realidad, ni siquiera hay una garantía de que algo sea “restaurado”. El caso ‘normal’ es que las variables tendrán el valor que tenían, antes de llamar a la función que resultó en el longjmp. En algunos casos, como se discutió anteriormente, pueden ser ‘golpeados’ por la restauración ciega de todos los registros de llamadas guardadas realizada por setjmp/longjmp. En la práctica, esto significa que, si se golpean, probablemente se restaurarán al valor ‘setjmp’, pero el lenguaje solo establece que son indeterminados en lugar de la última vez que los configuró.

    – grego

    4 de noviembre de 2016 a las 15:07


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad