Анатомия C Run-Time, или Как сделать программу немного меньшего размера - Код инициализации глобальных переменных
ОГЛАВЛЕНИЕ
Код инициализации глобальных переменных
Как в VC++ реализован вызов цепочки функций инициализации/завершения?
Наличие в программе хотя бы одной глобальной переменной - экземпляра класса - заставляет компилятор сделать следующее. Во-первых, он генерирует невидимую за пределами модуля функцию, в которой и выполняются необходимые действия - вычисляется значение инициализатора или вызывается конструктор. Далее создается специальная запись с указателем на эту функцию в сегменте с именем вида ".CRT$xxx". Детально разбирать формат именования сегмента мы не будем, сейчас важно только то, что все сегменты такого типа будут при сборке объединены в алфавитном порядке в один сегмент. Таким образом, в момент старта программы в памяти будет находиться массив указателей на функции, при вызове которых и произойдут необходимые действия. В стартовом коде CRT VC этим занимается функция _initterm.
А почему здесь используется термин "функции инициализации/завершения " вместо терминов "конструкторы/деструкторы"?
Напомню, что стандарт языка C++ разрешает инициализацию переменных с помощью неконстантных выражений. Если переменная (даже простого типа) описана в глобальной области, то ее инициализатор должен быть выполнен до вызова функции main/WinMain:
int len = strlen("Hello, world!");
Обработка в этом случае ничем не отличается от инициализации экземпляра класса имеющего конструктор.