Даже в C необходимо, чтобы какой-то код выполнялся до ввода main()
, чтобы преобразовать командную строку в соглашение о вызовах C. На практике стандартная библиотека требует некоторой инициализации, и точные потребности могут варьироваться от компиляции к компиляции.
Истинная точка входа в программу устанавливается во время соединения и обычно находится в модуле с именем, подобным crt0
по историческим причинам. Как вы обнаружили, исходный код этого модуля доступен в источниках crt.
Для поддержки инициализаций, обнаруженных во время соединения, используется специальный сегмент. Его структура представляет собой список указателей на функции с фиксированной сигнатурой, которые будут повторяться в начале crt0
и вызывать каждую функцию. Этот же массив (или очень похожий) указателей на функцию используется в ссылке на C ++ для хранения указателей на конструкторы глобальных объектов.
Массив заполняется компоновщиком, позволяя каждому связанному модулю включать в него данные, которые объединяются вместе для формирования сегмента в готовом исполняемом файле.
Единственное значение для переменной pinit
заключается в том, что она объявлена (макросом _CRTALLOC()
) для размещения в этом сегменте и инициализирована по адресу функции, вызываемой во время запуска Си.
Очевидно, детали этого чрезвычайно специфичны для платформы. Для общего программирования вам, вероятно, лучше обернуть инициализацию и текущую основную часть в новый main()
:
int main(int argc, char **argv) {
early_init();
init_that_modifies_argv(&argc, &argv);
// other pre-main initializations...
return real_main(argc,argv);
}
Для специальных целей наилучшим ответом может быть изменение самого модуля crt0
или выполнение специфических для компилятора приемов для вызова дополнительных функций ранней инициализации. Например, при создании встроенных систем, которые запускаются из ПЗУ без загрузчика операционной системы, обычно необходимо настроить поведение модуля crt0
, чтобы вообще иметь стек для передачи параметров в main()
, В этом случае, возможно, нет лучшего решения, чем модифицировать crt0
для инициализации аппаратного обеспечения памяти в соответствии с вашими потребностями.