Влияет ли использование __declspec (selectany) со статическими данными на порядок инициализации этих данных? - PullRequest
3 голосов
/ 18 февраля 2012

Я использую стороннюю библиотеку C ++, для которой требуется определение глобального массива структур. Мне не нравится этот дизайн, но я застрял с ним.

LibStruct g_Structs[] = 
{
  { /* structure initialization data */ },
  { /* structure initialization data */ },
      // etc
};
int g_NumStructs = sizeof(g_Structs) / sizeof(g_Structs[0]);

Я бы хотел немного разбить это, чтобы классы могли предоставить определение структуры, которое применимо к этому классу. Это может привести к фиаско статической инициализации, если инициализация не будет выполнена безопасно с использованием геттеров или после начала main ().

Если я объявляю MyStructs для каждого класса в заголовочном файле для этого класса как статические члены данных с атрибутом __declspec (selectany) (специфичным для Visual C ++), тогда кажется работающим. Влияет ли атрибут selectany на порядок построения этих данных? Означает ли появление определения selectany статического члена данных перед глобальным массивом фактически то, что он построен в таком порядке? Или это поведение зависит только от того, какое из определений множественного выбора выбрасывается компоновщиком? Есть ли гарантии у selectany?

// In the header for Class1
static const LibStruct __declspec(selectany) Class1::m_MyStruct = { /* structure initialization data */ };

// In the header for Class2
static const LibStruct __declspec(selectany) Class2::m_MyStruct = { /* structure initialization data */ };

// Danger - potential for static initialization fiasco?
LibStruct g_Structs[] = 
{
    Class1::m_MyStruct,
    Class2::m_MyStruct,
    // etc
};
int g_NumStructs = sizeof(g_Structs) / sizeof(g_Structs[0]);

РАЗЪЯСНЕНИЯ:

В этом случае MyStruct - это структура в стиле C, которая не имеет конструкторов или виртуальных функций и содержит только указатели, которые все инициализированы, чтобы указывать на другие глобальные данные или функции, не являющиеся членами. Поэтому инициализация глобального константного MyStruct с использованием синтаксиса = {} не должна запускать код конструктора.

1 Ответ

2 голосов
/ 21 января 2015

Добавление моего собственного ответа, так как других ответов не было.

Кажется, что этот код будет работать, но только потому, что реализация компилятора Microsoft решает инициализировать глобальные константные примитивные данные, отображая их в памяти израздел .data исполняемого образа перед выполнением любого статического кода инициализации.Таким образом, это зависит от реализации, но зависит от стратегии статической инициализации компилятора, а не от использования __declspec (selectany).

Переход по точке входа приложения показывает, что это выглядит правильно.Статические объекты Mystruct const уже инициализируются в точке входа, но глобальный массив инициализируется позже в статическом строительном коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...