gpt4 book ai didi

c++ - C++ 库中静态 STL 容器的双重初始化

转载 作者:可可西里 更新时间:2023-11-01 18:34:47 24 4
gpt4 key购买 nike

这里有一些关于“静态初始化顺序失败”的很好的问题和答案,但我似乎遇到了它的另一种表达方式,特别难看,因为它不会崩溃,但会丢失和泄漏数据。

我有一个自定义 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

问题来了,静态vector是重新初始化的,还是在初始化之前就使用了?这是预期的行为吗?

如果我将库“ar”为“mylib.a”(ar rcs mylib.a mylib.o),问题就不会发生,但可能是因为只有一个有效的命令链接到 .a 而它就是把库放在最后,至于这里的 myapp1。

但在我们的实际应用程序中,一个更复杂的应用程序,包含许多目标文件和一些共享一些静态注册表的静态 (.a) 库,问题正在发生,到目前为止我们设法解决它的唯一方法是应用'[10.15] How do I prevent the "static initialization order fiasco"?' .

(我仍在研究我们有点复杂的构建系统,看看我们是否正确链接)。

最佳答案

解决初始化顺序问题的一种方法是将静态变量从全局范围移动到局部范围。

与其在类中使用 registry 变量,不如将其放入函数中:

vector<string> & MyLibClass::GetRegistry()
{
static vector<string> registry;
return registry;
}

在您将直接使用 registry 的地方,让它调用 GetRegistry

关于c++ - C++ 库中静态 STL 容器的双重初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5422579/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com