2013-03-05 2 views
6

Section 16.4 of C++ FAQs (2nd Edition) (Paperback) by Marshall P. Cline, Greg Lomow говорит, что встроенные функции не могут безопасно обращаться к элементам статических данных, поскольку функция может быть вызвана до инициализации элемента статических данных.встроенные функции доступа к статическому?

Я не понимаю, почему это относится к встроенным функциям, а не к каким-либо функциям в других единицах перевода, которые вызывают статический член данных в другой единицы перевода? Я не вижу, какая часть «inline» играет в этой катастрофе?

+0

Я никогда не думал об этом раньше, но да, это проблема, не так ли? –

+0

Какой часто задаваемый вопрос? – Slava

+0

Обычно «C++ FAQ» относится к [this] (http: // http: //www.parashift.com), но [16.4 на этом сайте не имеет ничего общего с встроенным или статическим] (http: // www. parashift.com/c++-faq/new-vs-malloc.html), поэтому я не уверен в этом случае. Я не могу найти эту проблему, упомянутую на сайте, на котором я вообще связан. –

ответ

6

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

§ 3.6.2/4 Реализовано определение того, выполняется ли динамическая инициализация нелокальной переменной со статической продолжительностью хранения до первого оператора основного. Если инициализация отложена до некоторого момента времени после первого утверждения main, она должна произойти до первого использования odr (3.2) любой функции или переменной, определенной в той же самой единицы перевода, что и инициализированная переменная.

и

§ 3.2/3 Функция инлайн должна быть определена в каждой единице перевода, в котором он ODR использовать.

встроенные функции на самом деле не являются более опасными, чем не встроенные функции, насколько я знаю. Любая функция, обращающаяся к статике в другом ТУ, является рискованной, и поскольку inline просто выполняет функции в каждый TU, большинство из них небезопасны. Одним из способов является использование "construct on first use idiom".

Неявные специализации шаблона являются сложными, но для полноты:

§ 14.7.1/3 [temp.inst] инициализация (и любые связанные с ними побочные эффекты) статического члена данных не происходит, если элемент статических данных сам используется таким образом, который требует определения статического члена данных.

Таким образом, статические члены классов шаблонов всегда инициализируются перед использованием.

Все вышеперечисленное подпадает под действие the static initialization order fiasco), которое решает вышеупомянутая «конструкция при первом использовании идома».

+0

Я боюсь, что это не утверждение: статические переменные инициализируются до того, как будет выполнена какая-либо функция в той же самой системе перевода (cpp-файл более или менее). – Slava

+0

@Slava: в случае, если вы подразумеваете динамическую и постоянную статическую инициализацию, я немного уточнил это предложение. –

+0

Он говорит, что если инициализация отложена ... – Slava

Смежные вопросы