Из любопытства, что именно происходит, когда загружается приложение, скомпилированное с MSVCR, соответственно. как загрузчик Windows на самом деле инициализирует CRT? Насколько я понял, когда программа и все импортированные библиотеки загружаются в память и все перемещения выполняются, код запуска CRT (_CRT_INIT()
?) инициализирует все глобальные инициализаторы в .CRT$XC*
разделы и вызовы, определенные пользователем main()
функция. Я надеюсь, что пока это правильно.
Но давайте предположим, для пояснения, что программа, которая не использует MSVCR (например, приложение, созданное с помощью Cygwin GCC или других компиляторов), пытается загрузить библиотеку во время выполнения, требуя CRT, используя пользовательский компоновщик загрузчика / среды выполнения, так нет LoadLibrary()
участвует. Как загрузчик / компоновщик должен обрабатывать инициализацию CRT? Должен ли он вручную инициализировать все «объекты» в указанных разделах, должен ли он делать что-то еще, чтобы внутренняя проводка библиотеки работала должным образом, или он должен был просто вызвать _CRT_INIT()
(что непрактично определено в самой среде выполнения и нигде не экспортируется, насколько я знаю). Будет ли эта путаница вообще работать каким-либо образом, предполагая, что не-CRT-приложение и CRT-библиотека не будут передавать между ними какие-либо объекты, исключения и тому подобное?
Мне было бы очень интересно узнать, потому что я не могу понять, как ЭЛТ влияет на фактический процесс загрузки …
Любая информация очень ценится, спасибо!
Каждая библиотека, скомпилированная для среды выполнения C ++, при загрузке вызывает _DllMainCRTStartup. _DllMainCRTStartup вызывает _CRT_INIT, который инициализирует библиотеку времени выполнения C / C ++ и вызывает конструкторы C ++ для статических, нелокальных переменных.
Формат PE содержит необязательный заголовок, в котором есть слот, называемый addressofentrypoint. Этот слот вызывает функцию, которая вызовет _DllMainCRTStartup, которая запускает цепочку инициализации.
после того как _DllMainCRTStartup завершит фазу инициализации, он вызовет вашу собственную реализованную функцию DllMain ().
Точка входа для исполняемого образа выбирается с помощью опции компоновщика / ENTRY. Используемые по умолчанию значения задокументированы в Статья библиотеки MSDN. Они являются точкой входа в ЭЛТ.
Если вы хотите заменить CRT, то либо выберите то же имя, либо явно используйте параметр / ENTRY при ссылке. Вам также понадобится / NODEFAULTLIB, чтобы он не связывал обычный .lib
Когда вы узнаете о программировании, кто-то скажет вам, что «первое, что происходит, это то, что код работает в main
, Но это немного похоже на то, когда вы узнаете об атомах в школе, они довольно хорошо организованы и действуют в соответствии со строгими правилами. Если вы позже пойдете на занятия по ядерной физике / физике частиц в университете, эти простые / строгие правила будут гораздо более подробными и не всегда будут применяться, и т. Д.
Когда вы связываете программу на C или C ++, CRT содержит некоторый код, похожий на этот:
start()
{
CRT_init();
...
Global_Object_Constructors();
...
exit(main());
}
Таким образом, инициализация выполняется самой библиотекой времени выполнения C, ДО того, как она вызывает вашу main.
DLL имеет DllMain
это выполняется LoadLibrary()
— это отвечает за инициализацию / создание глобальных объектов в DLL, и если вы не используете LoadLibrary()
[например. загружая DLL в память самостоятельно], тогда вы должны убедиться, что объекты созданы и инициализированы.