2011-09-01 41 views
9

Programación avanzada en el entorno UNIX por W. Richard Stevens afirma:¿Qué es una variable automática en este contexto setjmp/longjmp?

"¿Cuáles son los estados de las variables automáticas y registran variables de la función principal?"

con respecto a lo que sucede cuando longjmp regresa a la función principal (u otra función) desde algún lugar más abajo en la pila.

Se llega a decir:

"Depende mayoría de las implementaciones no tratan de hacer retroceder estas variables automáticas y registrar las variables, pero todo lo que las normas decir es que sus valores son indeterminados.. Si usted tiene una variable automática que no desea que se deshace, definirla con el atributo volatile. las variables que se declaran global o estática se quedan solos cuando se ejecuta longjmp.

Parece que está diciendo que las variables de pila normales no tendrán sus valores establecidos en lo que eran en el momento del setjmp, pero que el resto de la función no podría depender de sus variables de pila después de la vuelta larga a lo que parece loco, así que supongo que estoy equivocado.

¿Alguien puede definir "variables automáticas" para mí y explicar qué específicamente no se establece en su valor original y por qué?

+1

Una variable automática es simplemente una con la clase de almacenamiento 'auto', que es la predeterminada en las variables de función que no tienen otra declaración de clase de almacenamiento. Es una palabra clave, ya sabes. – tchrist

Respuesta

6

Todo lo que está diciendo es que si

  1. que tienen una variable automática (función local-no estática) que no está declarado volatile; y
  2. cambia el valor de la variable entre setjmp y longjmp

continuación, después de la longjmp el valor de esa variable se convierte en indeterminado.

Creo que esto tiene que ver con la posibilidad de que tales variables residan en los registros de la CPU en lugar de en la RAM, y la dificultad asociada de preservar los valores de dicha variable en el longjmp.

Aquí es una cita de la gcc manual:

Si utiliza longjmp, tenga cuidado con las variables automáticas. ISO C dice que las variables automáticas que no están declaradas volatile tienen valores indefinidos después de longjmp. Y esto es todo lo que GCC promete hacer, porque es muy difícil restaurar las variables de registro correctamente, y una de las características de GCC es que puede poner variables en los registros sin que le pida.

Si la posible pérdida de valores de las variables es un problema en su caso de uso, declare las variables relevantes como volatile.

+3

Por supuesto, esa cita manual de gcc es una explicación pobre: ​​eso no es realmente lo que dice ISO C. Solo lo hace indefinido _si están modificados_, y lo que es difícil no es restaurarlos (después de todo, puedes guardar y restaurar TODOS los registros) pero _avocar_ la restauración no deseada. – Random832

+0

De hecho, el * reason * para este UB es que es fácil guardar todos los valores de registro y restaurarlos, pero no es práctico que la implementación realice un seguimiento de * qué copia del valor * (el que está en la memoria o el almacenado en caché en un registro) fue el más actualizado en el momento del 'longjmp'. –

+0

@ Random832: Gracias. He editado la respuesta para intentar aclarar las cosas. – NPE

6

"Variables automáticas" es un término antiguo para variables locales ordinarias (no declaradas con registro o estáticas), que se remonta a la terminología utilizada en el estándar C y el significado original de la palabra clave auto. Véanse las secciones 6.2.4 y 6.7.1 de the standard

En cuanto a esto:

pero luego el resto de la función no podían confiar en sus variables de pila después de la longjmp de nuevo a él, que parece una locura

La idea es que no debe modificarlas en primer lugar si va a hacer longjmp porque entonces no puede saber qué va a pasar.

El razón es que longjmp puede restaurar el estado, tales como los registros del procesador, que las variables automáticas pueden haber sido asignados a (no hay garantía de que van a estar en "la pila" o en la memoria en absoluto. Y aunque existen en la memoria, algunas operaciones pueden no acceder directamente a la memoria [a menos que se declare volátil], pero pueden acceder a un registro del procesador en el que ya se ha cargado el valor)

Su pregunta es extraña porque implica que usted sería quiere que se restauren [es decir sus modificaciones en las funciones intermedias deben borrarse] - en general, esta advertencia advierte que pueden ser restauradas por accidente cuando no se espera. "No restaurado" no significa "inutilizable" [aunque el estándar LO declara inutilizable porque podría restaurar un registro en caché pero no la memoria, por lo que obtendrá resultados inconsistentes], significa "tiene el valor que escribió una función posterior" (porque pasaste la dirección con la intención de escribirlo) ".

+0

Es extraño que tanta gente hoy en día parezca haber olvidado las cuatro palabras clave [clase de almacenamiento] de C (http://en.wikipedia.org/wiki/Static_variable) para sus variables: 'auto',' static', 'register' y 'extern' - aunque una variable' volátil 'es [algo diferente] (http://en.wikipedia.org/wiki/Volatile_variable), y dudosa en el mejor de los casos. – tchrist

0

auto significa cualquier cosa que sea local para la función y no se ha definido específicamente como static. Es probablemente la pena señalar que la norma especifica más o menos el comportamiento afirma (§7.13.2/3):

Todos los objetos accesibles tener valores, y todos los demás componentes de la máquina abstracta tener estado, a partir de la tiempo en que se llamó a la función longjmp, excepto que los valores de objetos de duración de almacenamiento automático que son locales para la función que contiene la invocación de la macro setjmp correspondiente que no tienen el tipo calificado volátil y se han cambiado entre la invocación setjmp y longjmp call son indeterminados.

0

No puedo definir una "variable automática", pero tal vez pueda ayudar a entender lo que sucede durante una setjump:

(algunos de) los registros de la CPU y se guarda en un archivo.

y durante longjump:

el valor de los registros de la CPU se restablece al valor guardado.

¡nada más! (here es un ejemplo)

Así que durante el longjump, que acaba de volver más alta en la pila, con todas sus variables guardadas en la memoria intacta, y algunos (no todos) de los registros, en especial el stack pointer y el instruction pointer se restablecieron al valor que tenían durante el setjmp.

Cuestiones relacionadas