靜態STL容器的雙初始化周圍有「靜態變量初始化順序的悲劇」了幾個很好的問題和答案在這裏,但我似乎已經撞到它的另一個表現,特別難看,因爲它不會崩潰但會泄漏並泄露數據。在C++庫
我有一個自定義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
問題來了,靜態載體重新初始化,還是在初始化之前使用?這是預期的行爲嗎?
如果我AR「圖書館作爲「mylib.a上」(AR RCS mylib.a上mylib.o),該問題不會發生,但可能是因爲只有一個有效的以鏈接到.A這是通過讓圖書館在最後一個地方,如myapp1在這裏。
但是在我們真正的應用程序中,一個包含許多目標文件和一些靜態庫(.a)的更復雜的庫共享一些靜態註冊表,問題正在發生,我們目前設法解決它的唯一方法是申請'[10.15] How do I prevent the "static initialization order fiasco"?'。
(我仍然在研究中我們有些複雜的編譯系統,看看我們是否已正確連接)。
非常好的示例代碼。我希望所有問題都是這樣的。 – 2011-03-24 17:14:54