Двойная инициализация статического контейнера STL в библиотеке C ++

Здесь есть несколько хороших вопросов и ответов по поводу «фиаско статического порядка инициализации», но я, кажется, наткнулся на еще одно его выражение, особенно уродливым, потому что он не дает сбоев, а приводит к потере и утечке данных.

У меня есть собственная библиотека C ++ и приложение, связанное с ней. В библиотеке есть статический контейнер STL, который регистрирует все экземпляры класса. Эти экземпляры оказываются статическими переменными в приложении.

В результате "фиаско" (я полагаю), мы получаем контейнер, заполненный экземплярами приложения во время инициализации приложения, затем инициализируется библиотека и контейнер становится сбросить (возможно, утечка памяти), в результате остались только экземпляры из библиотеки.

Вот как я воспроизвел его с помощью упрощенного кода:

mylib.hpp:

#include 
#include 
#include 

using namespace std;

class MyLibClass {
    static vector registry;
    string myname;
  public:
    MyLibClass(string name);
};

mylib.cpp:

#include "mylib.hpp"

vector MyLibClass::registry;

MyLibClass::MyLibClass(string name)
: myname(name)
{
    registry.push_back(name);
    for(unsigned i=0; i

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] Как мне предотвратить «фиаско статического порядка инициализации»? ».

(Я все еще изучаю нашу довольно сложную систему сборки, чтобы узнать, мы связываемся правильно).

7
задан James McNellis 24 March 2011 в 17:03
поделиться