__attribute __ ((init_priority (X))) в GCC - PullRequest
5 голосов
/ 30 июля 2010

Я использую __attribute__((init_priority(X))) в GCC следующим образом:

Type1 __attribute__ ((init_priority (101))) name1 = value1;
Type2 __attribute__ ((init_priority (102))) name2 = value2;

в разных исходных файлах. Допустим, file1.cpp и file2.cpp. Если я использую это в той же библиотеке, это работает как положено, name1 инициализируется перед name2, но если я использую это в разных библиотеках, порядок инициализации не является ожидаемым. Я прочитал на gcc документацию, что это должно работать в разных библиотеках, как я ожидаю, чтобы определить порядок инициализации. Что-то не так в том, как я это использую? У вас была такая же проблема?

PS: рефакторинг не является решением этой проблемы, потому что я должен портировать очень большой проект из Visual Studio.

Ответы [ 5 ]

7 голосов
/ 09 августа 2010

В документации gcc (gcc 4.4) написано:

`init_priority (PRIORITY) '

В стандарте C ++ объекты, определенные в области имен, гарантированы инициализироваться в порядке в строгом соответствии с их определения в заданной единице перевода . Нет гарантии сделано для инициализации через единицы перевода. Тем не менее, GNU C ++ позволяет пользователям контролировать порядок инициализации объектов определяется в области имен с помощью атрибута init_priority указание относительного приоритета, константное интегральное выражение в настоящее время ограничено между 101 и 65535 включительно. Нижние числа указать более высокий приоритет.

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

Однако разделяемые библиотеки фактически являются исполняемыми файлами сами по себе - в рамках данной разделяемой библиотеки инициализация выполняется в указанном порядке, но совместно используемые библиотеки инициализируются как единое целое в порядке, указанном динамическим загрузчиком, т.е. liba. он загружается до или после libb.so в соответствии с критериями упорядочения загрузчика, и атрибут init_priority не может влиять на это упорядочение.

0 голосов
/ 05 августа 2010

Все ли рассматриваемые объекты находятся в одной области имен (я предполагаю, что они глобальные)? В документации GCC я не видел никакой гарантии того, что это необходимо для работы в разных библиотеках (хотя для компоновщика было бы целесообразно сделать это).

Несмотря на ваше последнее замечание, я все еще собираюсь предложить рефакторинг. Если у вас есть контроль над кодом для использования __attribute__, то вы можете, по крайней мере, использовать функцию-экземпляр «обертки», которая использует статическую локальную переменную для инициализации. Это потребовало бы некоторого изменения кода, но в целом это должно быть возможно сделать полуавтоматическим способом. Смотри http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.13.

Также обратите внимание, что если вы исправляете / реорганизуете код, вы не рискуете, что патч / обновление компилятора для вашего VS-компилятора внезапно нарушит код, возможно, неочевидными способами.

0 голосов
/ 30 июля 2010

Если вы хотите, чтобы ваши вещи были инициализированы по порядку, попробуйте создать функцию инициализации с помощью __attribute__((constructor (priority))).

0 голосов
/ 05 августа 2010

С помощью GNU linker ваши общие библиотеки будут инициализироваться одна за другой в порядке их зависимостей, а не параллельно.Это означает, что если ваш двоичный файл зависит от разделяемой библиотеки, то разделяемая библиотека инициализируется до начала динамической инициализации в вашем двоичном файле.

0 голосов
/ 30 июля 2010

Если ваша библиотека динамическая, т.е. .so, а не .a, то ld будет влиять на порядок вещей, а gcc может контролировать только порядок init в пределах того же самого двоичного файла ELF (который будет суммой всех.o и .a).

...