fiasco de orden de inicialización estática

Estaba leyendo sobre SIOF de un libro y dio 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á lo siguiente?

  1. al comstackr file1.cpp, el comstackdor deja y tal como está, es decir, no asigna almacenamiento para él.
  2. el comstackdor asigna almacenamiento para x, pero no lo inicializa.
  3. Al comstackr file2.cpp, el comstackdor deja x como está, es decir, no asigna almacenamiento para él.
  4. el comstackdor asigna almacenamiento para y, pero no lo inicializa.
  5. Mientras enlaza file1.o y file2.o, ahora permite que file2.o se inicialice primero, así que ahora:
    ¿X obtiene un valor inicial de 0? o no se inicializa?

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

Paso 1: y se inicializan a cero antes de que se lleve a cabo cualquier otra inicialización.

Paso 2: x o y se inicializa dinámicamente, que no está especificado por el estándar. Esa variable obtendrá el valor 1 ya que la otra variable tendrá cero inicialización.

Paso 3: la otra variable se inicializará dinámicamente, obteniendo el valor 2 .

SIOF es en gran medida un artefacto de tiempo de ejecución, el comstackdor y el enlazador no tienen mucho que ver con eso. Considere la función atexit (), registra las funciones a las que se llamará al salir del progtwig. Muchas implementaciones de CRT tienen algo similar para la inicialización del progtwig, llamémoslo atinit ().

Inicializar estas variables globales requiere ejecutar el código, el valor no puede ser determinado por el comstackdor. Entonces el comstackdor genera fragmentos de códigos de máquina que ejecutan la expresión y le asignan el valor. Estos fragmentos deben ejecutarse antes de que se ejecute main ().

Ahí es donde atinit () entra en juego. Una implementación común de CRT recorre una lista de punteros de función atinit y ejecuta los fragmentos de inicialización, en orden. El problema es el orden en que las funciones se registran en la lista atinit (). Mientras que atexit () tiene una orden LIFO bien definida, y está implícitamente determinada por el orden en que el código llama a atexit (), tal no es el caso para las funciones atinit. La especificación del idioma no requiere un pedido, no hay nada que pueda hacer en su código para especificar un pedido. SIOF es el resultado.

Una posible implementación es el comstackdor que emite punteros a las funciones en una sección separada. El enlazador los fusiona, produciendo la lista atinit. Si su comstackdor hace eso, entonces la orden de inicialización estará determinada por el orden en el que vincula los archivos del objeto. Mira el archivo de mapa, deberías ver la sección de atinit si tu comstackdor hace esto. No se llamará atinit, pero es probable que aparezca algún tipo de nombre con “init”. Echar un vistazo al código fuente de CRT que llama a main () también debería darnos una idea.

El punto (y la razón por la que se llama un “fiasco”) es que es imposible decir con certeza qué sucederá en un caso como este. Básicamente, estás pidiendo algo imposible (que cada una de las dos variables sea una más grande que la otra). Como no pueden hacer eso, lo que harán está abierto a alguna pregunta: pueden producir 0/1, o 1/0, o 1/2, o 2/1, o posiblemente (el mejor de los casos) solo un error. mensaje.

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

Las variables estáticas generalmente se inicializan a cero a menos que tengan un inicializador constante. De nuevo, esto depende del comstackdor. Entonces, una de estas variables probablemente será cero cuando la otra se inicialice. Sin embargo, dado que ambos tienen inicializadores, algunos comstackdores pueden dejar los valores indefinidos.

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

  1. El espacio se asigna para las variables, y ambos tienen el valor 0.
  2. Una variable, digamos x, se inicializa y se establece en el valor 1.
  3. El otro, digamos y, se inicializa y se establece en el valor 2.

Siempre puedes ejecutarlo y ver. Podría ser que algunos comstackdores generen código que entra en un ciclo infinito.