Pregunta

Yo estaba leyendo acerca de SIOF de un libro y se lo di un ejemplo:

//file1.cpp
extern int y;
int x=y+1;

//file2.cpp
extern int x;
int y=x+1;  

Ahora mi pregunta es:
En el código anterior, sucederán siguientes cosas?

  1. durante la compilación de file1.cpp, hojas de compilación y de igual modo, es es decir no asigna almacenamiento para la misma.
  2. compilador reserva espacio para x, pero no inicializarlo.
  3. Al compilar file2.cpp, hojas compilador x, ya que es es decir no asigna almacenamiento para la misma.
  4. compilador reserva espacio para y, pero no inicializarlo.
  5. Si bien la vinculación file1.o y file2.o, ahora vamos file2.o se inicializa en primer lugar, por lo que ahora:
    ¿El x consigue valor inicial de 0? o no hace que éste se inicia?
¿Fue útil?

Solución

Los pasos de inicialización se dan en 3.6.2 "Inicialización de objetos no locales" de la C ++ estándar:

Paso 1: x y y son cero-inicializado antes de cualquier otra inicialización tiene lugar.

Paso 2: x o y se inicializa dinámicamente - que uno es no especificado por el estándar. Esa variable se consigue la 1 valor desde la otra variable habrá sido inicializado a cero.

Paso 3:. La otra variable se inicializa de forma dinámica, para obtener el valor 2

Otros consejos

SIOF es en gran medida un artefacto de tiempo de ejecución, el compilador y el enlazador no tienen mucho que ver con ello. Considere la función atexit (), se registra funciones a ser llamados al salir del programa. Muchas implementaciones CRT tienen algo similar para el inicio del programa, vamos a llamarlo atinit ().

La inicialización de estas variables globales requiere la ejecución de código, el valor no puede ser determinada por el compilador. Por lo que el compilador genera fragmentos de código máquina que ejecutan la expresión y asigna el valor. Estos fragmentos deben ser ejecutados antes de main () se ejecuta.

Es donde atinit () entra en juego. Una aplicación común CRT recorre una lista de atinit punteros de función y ejecución de los fragmentos de inicialización, en orden. El problema es el orden en el que las funciones están registrados en la lista atinit (). Mientras atexit () tiene un orden LIFO bien definido, y se determina implícitamente por el orden en el que el código llama atexit (), tal no es el caso para las funciones atinit. La especificación del lenguaje no requiere una orden, no hay nada que hacer en el código para especificar un orden. SIOF es el resultado.

Una posible implementación es el compilador que emiten los punteros de función en una sección separada. El enlazador las fusiona, produciendo la lista atinit. Si el compilador lo hace, entonces el orden de inicialización será determinado por el orden en que se vinculan los ficheros objeto. Mira el archivo de mapa, debería ver la sección atinit si su compilador hace esto. No se llamará atinit, pero algún tipo de nombre con "init" es probable. Echando un vistazo al código fuente CRT que llama main () debe dar una idea así.

El punto (y la razón por la que se llama un "fracaso") es que es imposible decir con certeza lo que ocurrirá en un caso como este. Esencialmente, usted está pidiendo algo imposible (que dos variables de cada uno más que el otro). Ya que no pueden hacer eso, lo que van a hacer es abrir a una pregunta - que podría producir 0/1 o 1/0, o 1/2, o 2/1, o posiblemente (mejor de los casos), justo un error mensaje.

Es compilador dependiente y tiempo de ejecución puede ser dependiente. Un compilador puede decidir las variables estáticas perezosamente initialize cuando se accede a la primera variable en un archivo, o como se accede a cada variable. De lo contrario, se inicializará todas las variables estáticas de archivo en el momento del lanzamiento, con el fin generalmente en función del orden de los vínculos de archivos. El orden de los archivos podría cambiar en función de las dependencias u otras influencias dependientes del compilador.

Las variables estáticas suelen ser inicializado a cero a menos que tengan un inicializador constante. Una vez más, esto es compilador dependiente. Así que una de estas variables probablemente será cero cuando el otro está inicializado. Sin embargo, ya que ambos tienen inicializadores algunos compiladores podrían dejar los valores no definidos.

Creo que el escenario más probable sería:

  1. El espacio se asigna a las variables, y ambos tienen el valor 0.
  2. Una variable, digamos x, se inicializa y se ajusta al valor 1.
  3. El otro, responde S, se inicializa y se ajusta al valor 2.

Siempre se puede ejecutarlo y ver. Podría ser que algunos compiladores generarían código que entra en un bucle infinito.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top