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