关于“静态初始化顺序惨败”,这里有一些很好的问题和答案,但我似乎遇到了它的另一种表达方式,特别丑陋,因为它不会崩溃但会丢失和泄漏数据。
我有一个自定义 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");
我的应用程序.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
问题来了,静态向量是重新初始化的,还是在初始化之前使用的?这是预期的行为吗?
如果我将库“ar”为“mylib.a”(ar rcs mylib.a mylib.o),则问题不会发生,但可能是因为只有一个有效的订单可以链接到 .a,而且它是通过图书馆在最后,至于 myapp1 这里。
但是在我们的实际应用程序中,一个包含许多目标文件和一些静态 (.a) 库的更复杂的应用程序共享一些静态注册表,问题正在发生,到目前为止,我们设法解决它的唯一方法是应用'[10.15 ] 如何防止“静态初始化命令惨败”?.
(我仍在研究我们有些复杂的构建系统,看看我们是否正确链接)。