Aquí hay algunas buenas preguntas y respuestas sobre el "fiasco de orden de inicialización estática", pero parece que he golpeado contra otra expresión de ella, especialmente fea porque no falla, pero pierde y pierde datos.Inicialización doble de un contenedor STL estático en una biblioteca C++
Tengo una biblioteca personalizada de C++ y una aplicación que enlaza con ella. Hay un contenedor STL estático en la biblioteca que registra todas las instancias de una clase. Esas instancias resultan ser variables estáticas en la aplicación.
Como resultado del "fiasco" (creo), obtenemos el contenedor lleno con las instancias de la aplicación durante la inicialización de la aplicación, luego la biblioteca se inicializa y el contenedor se reinicia (probablemente con pérdida de memoria), terminando solo con las instancias de la biblioteca.
Esta es la forma en que lo reprodujeron con código simplificado:
mylib.hpp:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class MyLibClass {
static vector<string> registry;
string myname;
public:
MyLibClass(string name);
};
mylib.cpp:
#include "mylib.hpp"
vector<string> MyLibClass::registry;
MyLibClass::MyLibClass(string name)
: myname(name)
{
registry.push_back(name);
for(unsigned i=0; i<registry.size(); i++)
cout << " ["<< i <<"]=" << registry[i];
cout << endl;
}
MyLibClass l1("mylib1");
MyLibClass l2("mylib2");
MyLibClass l3("mylib3");
MyApp.cpp:
#include "mylib.hpp"
MyLibClass a1("app1");
MyLibClass a2("app2");
MyLibClass a3("app3");
int main() {
cout << "main():" << endl;
MyLibClass m("main");
}
Compilar los objetos con:
g++ -Wall -c myapp.cpp mylib.cpp
g++ myapp.o mylib.o -o myapp1
g++ mylib.o myapp.o -o myapp2
Run myapp1:
$ ./myapp1
[0]=mylib1
[0]=mylib1 [1]=mylib2
[0]=mylib1 [1]=mylib2 [2]=mylib3
[0]=mylib1 [1]=mylib2 [2]=mylib3 [3]=app1
[0]=mylib1 [1]=mylib2 [2]=mylib3 [3]=app1 [4]=app2
[0]=mylib1 [1]=mylib2 [2]=mylib3 [3]=app1 [4]=app2 [5]=app3
main():
[0]=mylib1 [1]=mylib2 [2]=mylib3 [3]=app1 [4]=app2 [5]=app3 [6]=main
Run myapp2:
$ ./myapp2
[0]=app1
[0]=app1 [1]=app2
[0]=app1 [1]=app2 [2]=app3
[0]=mylib1
[0]=mylib1 [1]=mylib2
[0]=mylib1 [1]=mylib2 [2]=mylib3
main():
[0]=mylib1 [1]=mylib2 [2]=mylib3 [3]=main
Aquí viene la pregunta, el vector estática fue re-inicializado , o usado antes de la inicialización? ¿Es esto un comportamiento esperado?
Si 'ar' la biblioteca como 'mylib.a' (ar rcs mylib.a mylib.o), el problema no ocurre, pero probablemente porque solo hay un orden válido para enlazar con .a y es por tener la biblioteca en el último lugar, como para myapp1 aquí.
Pero en nuestra aplicación real, una más compleja con muchos archivos de objetos y algunas bibliotecas estáticas (.a) compartiendo unos pocos registros estáticos, el problema está sucediendo y la única manera en que logramos resolverlo es por aplicando '[10.15] How do I prevent the "static initialization order fiasco"?'.
(Todavía estoy investigando en nuestro sistema de compilación algo complejo para ver si estamos enlazando correctamente).
Muy buen código de muestra por cierto. Ojalá todas las preguntas se vieran así. –