这里有一些关于“静态初始化顺序惨败”的好问题和答案,但我似乎已经遇到了它的另一个表达,特别难看,因为它不会崩溃但是会丢失并泄漏数据.
我有一个自定义C库和一个链接它的应用程序.库中有一个静态STL容器,用于注册类的所有实例.这些实例碰巧是应用程序中的静态变量.
由于“惨败”(我相信),我们在应用程序初始化期间让容器填满应用程序实例,然后库进行初始化并重置容器(可能是泄漏内存),最后只有来自实例的实例图书馆.
这是我用简化代码复制它的方式:
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"); }
使用以下代码编译对象:
g++ -Wall -c myapp.cpp mylib.cpp g++ myapp.o mylib.o -o myapp1 g++ mylib.o myapp.o -o myapp2
运行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
运行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
问题是,静态向量是重新初始化的,还是在初始化之前使用的?这是预期的行为吗?
如果我把’库’作为’mylib.a'(ar rcs mylib.a mylib.o),问题不会发生,但可能是因为只有一个有效的订单链接到.a而且它是通过最后一个库,就像myapp1一样.
但是在我们的实际应用程序中,一个包含许多目标文件和一些静态(.a)库的更复杂的应用程序共享一些静态注册表,问题正在发生,到目前为止我们设法解决它的唯一方法是应用‘[10.15] How do I prevent the “static initialization order fiasco”?’.
(我仍在研究我们有些复杂的构建系统,看看我们是否正确连接).