Безопасно ли использовать getenv() в статических инициализаторах, то есть перед main()?

StackOverflow https://stackoverflow.com/questions/437279

Вопрос

я заглянул Стивенс, и в Руководство программиста Posix, и лучшее, что я могу найти, это

Массив строк, называемый окружающая среда становится доступным в начале процесса.На этот массив указывает внешняя переменная environ, который определяется как:

extern char **environ;

Это то, что окружать переменная, которая заставляет меня колебаться.я хочу сказать

- Вызывающий процесс/оболочка уже выделил блок строк с нулевым завершением.

-внешняя переменная environ используется в качестве точки входа getenv().

-ipso facto не стесняйтесь звонить getenv() внутри статического инициализатора.

Но я не могу найти никакой гарантии, что «статическая инициализация» окружать предшествует всему остальному статическому коду инициализации.Я слишком много об этом думаю?

Обновлять

На мой платформа (AMD Opteron, Redhat 4, GCC 3.2.3), настройка LD_DEBUG показывает, что окружать устанавливается до мои статические инициализаторы вызываются.Это приятно знать;спасибо, @codelogic.Но это не обязательно тот результат, который я получу на всех платформах.

Кроме того, хотя я интуитивно согласен с @ChrisW в отношении поведения библиотеки времени выполнения C/C++, это всего лишь моя интуиция, основанная на опыте.Так что любой, кто может привести цитату из какого-то авторитетного источника, гарантирующего, что окружать есть ли перед вызовом статических инициализаторов, бонусные баллы!

Это было полезно?

Решение

Я думаю, вы можете запустить свою программу с установленным LD_DEBUG, чтобы увидеть точный порядок:

LD_DEBUG=all <myprogram>

РЕДАКТИРОВАТЬ:Если вы посмотрите исходный код компоновщика времени выполнения (glibc 2.7), а именно в файлах:

  • sysdeps/unix/sysv/linux/init-first.c
  • sysdeps/i386/init-first.c
  • csu/libc-start.c
  • sysdeps/i386/elf/start.S

вы увидите, что argc, argv и environ (псевдоним __environ) устанавливаются перед вызовом каких-либо глобальных конструкторов (функций инициализации).Вы можете следить за выполнением, начиная прямо с _start, фактической точки входа (start.S).Как вы процитировали Стивенса «Массив строк, называемый средой, становится доступным в начале процесса», предполагая, что назначение среды происходит в самом начале инициализации процесса.Это, подкрепленное кодом компоновщика, который делает то же самое, должно дать вам достаточное спокойствие :-)

РЕДАКТИРОВАТЬ 2: Также стоит упомянуть, что environ устанавливается достаточно рано, поэтому даже компоновщик времени выполнения может запросить его, чтобы определить, следует ли выводить подробный вывод (LD_DEBUG).

Другие советы

Учитывая, что как настройка среды, так и вызов статических инициализаторов являются функциями, которые должна выполнять среда выполнения языка до вызова main (), я не уверен, что вы найдете гарантию Вот. То есть я не знаю конкретного требования, чтобы этот имел для работы и чтобы порядок гарантировался до main (), скажем, в спецификациях языка и библиотек ANSI или чего-то еще ... .но я тоже не проверял.

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

Исходя из этого, я голосую за то, что ожидал, что это сработает, это безопасное предположение, и текущие данные, кажется, поддерживают эту линию рассуждений.

По моему опыту, библиотека времени выполнения C инициализируется до того, как среда выполнения вызывает инициализаторы ваших статических переменных (и поэтому ваши инициализаторы могут вызывать функции библиотеки времени выполнения C).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top