2009-09-08 17 views
20

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

código

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 de la longjmp tiempo() fue llamado, excepto que los valores de los objetos de duración de almacenamiento automático que son locales para la función que contiene la invocación del setjmp() correspondiente que no tienen un tipo calificado volátil y que se cambian entre la invocación setjmp() y la llamada longjmp() son indeterminadas. "

veo después de dos posibles interpretaciones:

intepretation1:

Las variables locales son restauradas, excepto los que son a la vez

  • no volátil y
  • cambió

intepretation2:

Las variables locales son restauradas, excepto

  • los que son no volátil y
  • los que se cambió

Según interpretation1 después longjmp única v1 no está definido. v2, v3, v4 están definidos. Según la interpretación2 después de longjmp solo se define v4. v1, v2, v3 no están definidos.

¿Cuál es la correcta?

BTW: Necesito una respuesta general ("portátil") que sea válida para todos los compiladores, es decir, probar con un compilador en particular no ayuda.

+0

Nota de implementación: Las variables que son cambiadas y no volátiles pueden ser como eran en el momento de longjmp, o pueden restaurarse a lo que eran en el momento de setjmp, dependiendo de la generación del código. Por lo tanto, "indeterminado". Entonces, si fueron * no * cambiados, estos dos valores son los mismos y es por eso que los vars sin cambios son seguros. – greggo

Respuesta

10

La interpretación 1 es correcta. Si se pretendía la Interpretación 2, el texto original habría utilizado "o que se modifican" en lugar de "y".

26

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

automático (también conocido como "local", Stack-asignado) variables que no son 'volátil' puede ser almacenados en registros en lugar de en la pila.

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

Además, un compilador especialmente inteligente puede evitar variables que se pueden inferir del estado de otra variable y calcularlas según demanda.

Sin embargo, si la variable es automático, pero no ha asignado un registro, puede ser cambiado por el código entre el setjmp y el longjmp ..

volátil está diciendo explícitamente que el compilador no para almacenar la variable en un registro . Así que 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 debe confiar en nada ('indeterminado').

+0

Y supongo que, a la inversa, las variables automáticas declaradas como 'register' * pueden * almacenarse en los registros, pero el compilador podría ignorar la sugerencia, por lo que tampoco puede garantizar que se restaurarán. – Michael

+0

@Michael en realidad Ni siquiera hay una garantía de que algo se "restaure". El caso "normal" es que las variables tendrán el valor que tenían, antes de llamar a cualquier función que resulte en longjmp. En algunos casos, como se discutió anteriormente, pueden ser 'aplastados' por la restauración ciega de todos los registros guardados por llamada realizados por setjmp/longjmp. En la práctica, esto significa que, si se eliminan, probablemente se restablecerán al valor 'setjmp', pero el lenguaje solo indica que son indeterminados en lugar de lo que se les asignó por última vez. – greggo

Cuestiones relacionadas