Почему моя внешняя переменная еще не инициализирована? - PullRequest
5 голосов
/ 01 февраля 2012

Я собираю общую библиотеку с двумя модулями компиляции: globals.cpp и stuff.cpp.Файл globals.cpp инициализирует несколько внешних переменных, которые используются в stuff.cpp.Проблема, с которой я сталкиваюсь, заключается в том, что код в stuff.cpp выполняется до того, как код в globals.cpp получил возможность присвоить значение внешним переменным.Например, я вижу кучу 0 используемых значений.Эта проблема зависит от того, на какой платформе я компилирую / запускаю код - некоторые работают, а некоторые нет.

Как можно решить эту проблему?Могу ли я заставить globals.cpp на запустить сначала?

Ответы [ 3 ]

6 голосов
/ 01 февраля 2012

Вы не можете (последовательным образом)

Но вы можете обойти это.

global.cpp

// If you have a global variable that has to be initial by a constructor
MyObj globalX; 

// Instead do this

MyObj& globalX() { static MyObj x; return x;}

У вас все еще есть глобальная переменная,Но, помещая его в функцию, мы знаем, когда он используется.Используя статический член функции, он инициализируется при первом вызове функции, но не после этого.Таким образом, вы знаете, что он будет правильно построен перед первым использованием.

0 голосов
/ 01 февраля 2012

Я предполагаю, что вы наблюдаете это поведение, поскольку вы выполняете встроенную инициализацию глобальных переменных без явного вызова функции. например globals.cpp:

 // top of source file

 #include "myincludes.h"

 CSomeClass someObject(432);
 int global_x = 42;
 int global_y = InitY();

Порядок конструктора и деструктора глобальных объектов и порядок инициализации глобальной переменной в основном недетерминирован. (Я бы предположил, не обращаясь к стандартным справочным страницам, что переменные в исходном файле инициализируются от верхнего объявления до нижнего, но порядок «какой исходный файл идет первым» не определен.)

Лучшее решение - не иметь глобальных объектов (где конструктор запускается перед какими-либо функциями в библиотеке) или иметь зависимость от порядка инициализации глобальной переменной.

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

В моей команде код, который запускается до "main" (или "DllMain"), строго запрещен. Другими словами, нет глобальных объектов. Нет функций для инициализации глобалов.

...