TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #259 3.63K
Цикл жизни non-local static storage duration переменных

В прошлом посте поговорили про локальные статические переменные и их цикл жизни. Сегодня в общем рассмотрим рождение и смерть всех нелокальных глобальных переменных.

Здесь важна оговорка, что объекты со static storage duration не обязаны быть помечены ключевым словом static! Этот термин употребляется для описания объектов, лишь время жизни которых является статическим. То есть более менее всех глобальных объектов. Все они существуют от момента создания до момента завершения программы. Поэтому просто написав:

int var = 1;



считайте, что вы объявили переменную со static storage duration.

Для краткости, вместо "объект со static storage duration" буду писать"глобальный объект".

Так вот. Для таких объектов существует строгий порядок инициализации, который состоит из определенных шагов и подшагов.

1️⃣ Статическая инициализация. В сущности, это установление значения, которое может быть проведено во время компиляции. Состоит из двух подшагов:

👉🏿 Первым, если возможно, идет константная инициализация. Проводится, когда инициализатор - константное выражение.

👉🏿 Во всех остальных случаях проводится Zero-инициализация.

2️⃣ Динамическая инициализация. Только после того, как проведена статическая инициализация, вступает в игру динамическая. Которая и является причиной static initialization order fiasco. Потому что дает очень мало гарантий по поводу порядка инициализации, одна из которых описана тут. Но в общем и целом, порядок инициализации глобальных объектов в разных юнитах трансляции не определен.
Обычно она происходит в рантайме, но если компилятор может, то он производит ее в compile-time при наличии определенных условий.

После инициализации переменная живет в течение всего времени существования программы до тех пор, пока она не завершится.

Если чуть подробнее и конкретнее про завершение, то при выходе из функции main происходят все стандартные процессы разрушения локальных переменных, но еще и вызов std::exit с возращаемым из мэйна значением в качестве аргумента. И вот std::exit одним из своих шагов триггерит вызов деструкторов глобальных объектов.

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

Это суперобобщенно, поэтому дальше будем раскрывать все эти стадии.

Cегодня без картинки, но вместо этого можете посмотреть короткий веселый видосик про цикл жизни программиста

Define cycle of your life. Stay cool.

#cppcore #compiler
  • 👍 18
  • 🔥 6
  • ❤ 1
More from @grokaemcpp
  1. Oct 14, 2026​​Что внутри std::condition_variable? #опытным Более менее все знакомы с примитивом синхро…
  2. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  3. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  4. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  5. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  6. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →