Поскольку вы уже знаете, что вам не следует полагаться на эту информацию, если она не является абсолютно необходимой, вот она. Мое общее наблюдение по различным цепочкам инструментов (MSVC, gcc / ld, clang / llvm и т. Д.) Заключается в том, что порядок, в котором ваши объектные файлы передаются компоновщику, является порядком, в котором они будут инициализированы.
Есть исключения из этого, и я не претендую на них всех, но вот те, с которыми я столкнулся:
1) Версии GCC до 4.7 фактически инициализируются в обратном порядке линии связи. Этот билет в GCC - это когда произошло изменение, и оно сломало множество программ, которые зависели от порядка инициализации (включая мою!).
2) В GCC и Clang использование приоритета функции конструктора может изменить порядок инициализации. Обратите внимание, что это применимо только к функциям, которые объявлены как «конструкторы» (то есть они должны запускаться так же, как и конструктор глобального объекта). Я попытался использовать такие приоритеты и обнаружил, что даже с наивысшим приоритетом для функции конструктора все конструкторы без приоритета (например, обычные глобальные объекты, функции конструктора без приоритета) будут инициализированы first . Другими словами, приоритет относится только к другим функциям с приоритетами, но настоящие первоклассные граждане - это те, у кого нет приоритета. Что еще хуже, это правило является противоположным в GCC до 4.7 из-за пункта (1) выше.
3) В Windows есть очень аккуратная и полезная функция точки входа общей библиотеки (DLL), называемая DllMain () , которая, если она определена, будет работать с параметром "fdwReason", равным DLL_PROCESS_ATTACH непосредственно после инициализации всех глобальных данных и до приложение-потребитель имеет возможность вызывать любые функции в DLL. В некоторых случаях это чрезвычайно полезно, и абсолютно не является аналогичным поведению на других платформах с GCC или Clang с C или C ++. Самое близкое, что вы найдете, - это создание функции конструктора с приоритетом (см. Пункт (2) выше), что совершенно не то же самое и не будет работать во многих случаях использования, для которых работает DllMain ().
4) Если вы используете CMake для генерации ваших систем сборки, что я часто делаю, я обнаружил, что порядок входных исходных файлов будет таким же, как у их результирующих объектных файлов, передаваемых компоновщику. Тем не менее, часто ваше приложение / DLL также связывается с другими библиотеками, и в этом случае эти библиотеки будут на линии связи после ваших исходных файлов. Если вы хотите, чтобы один из ваших глобальных объектов был самым первым для инициализации, то вам повезло, и вы можете поместить исходный файл, содержащий этот объект, первым в список исходных файлов. , Однако, если вы хотите, чтобы один из них был самым последним для инициализации (который может эффективно реплицировать поведение DllMain ()!), Тогда вы можете сделать вызов add_library () с этим одним исходным файлом для создания статическую библиотеку и добавьте полученную статическую библиотеку в качестве самой последней зависимости ссылки в вызове target_link_libraries () для вашего приложения / DLL. Будьте осторожны, в этом случае ваш глобальный объект может быть оптимизирован, и вы можете использовать флаг - whole-archive , чтобы заставить компоновщик не удалять неиспользуемые символы для этого конкретного крошечного архивного файла.
Закрывающий совет
Чтобы полностью узнать результирующий порядок инициализации вашей связанной приложения / разделяемой библиотеки, передайте --print-map в ld linker и grep для .init_array (или в GCC до 4.7, grep для .ctors). Каждый глобальный конструктор будет напечатан в том порядке, в котором он будет инициализирован, и помните, что в GCC этот порядок противоположен до 4.7 (см. Пункт (1) выше).
Мотивирующим фактором для написания этого ответа является то, что мне нужно было знать эту информацию, у меня не было другого выбора, кроме как полагаться на порядок инициализации, и я обнаружил только редкие фрагменты этой информации в других сообщениях SO и интернет-форумах. Большая часть этого была изучена в результате многих экспериментов, и я надеюсь, что это сэкономит некоторым людям время на это!