Я ищу более техническое объяснение, чем ОС вызывает функцию. Кто-нибудь может мне помочь или указать мне на сайт или книгу?
Файл .exe (или эквивалент на других платформах) содержит адрес «точки входа». В первом приближении ОС загружает соответствующие разделы .EXE-файла в ram, а затем переходит к точке входа.
Как уже говорили другие, эта точка входа не будет «основной», но вместо этого будет частью библиотеки времени выполнения - она будет выполнять такие вещи, как инициализация статических объектов, настройка параметров argc / argv, настройка stdin / stdout / stderr и т. д. Когда все это будет сделано, он вызовет вашу функцию main (). При выходе из main среда выполнения проходит через сложный процесс передачи кода возврата обратно в среду, вызова статических деструкторов, вызова процедур _atexit и т. Д.
Если у вас есть инструменты MS (возможно, не бесплатные), то у вас есть весь источник времени выполнения, и простой способ взглянуть на него - установить точку останова на закрывающую скобку вашего метода main () и сделать один шаг назад во время выполнения.
main()
является частью библиотеки C и не является системной функцией. Я не знаю, для OS X или Linux, но Windows обычно запускает программу с WinMainCRTStartup()
. Этот символ запускает ваш процесс, извлекает аргументы командной строки, а также environment ( argc, argv, end
) и вызовы main()
. Он также отвечает за вызов любого кода, который должен запускаться после main()
, например atexit()
.
Посмотрев в свой файл Visual Studio, вы сможете найти реализацию по умолчанию, WinMainCRTStartup
чтобы увидеть, что он делает.
Вы также можете определить собственную функцию для вызова при запуске, это делается путем изменения «точки входа» в настройках компоновщика. Это часто функция, которая не принимает аргументов и возвращает пустоту.
Вы можете взглянуть на следующие ссылки:
В Expert C ++ / CLI (см. Стр. 279) есть очень конкретные детали различных сценариев начальной загрузки для собственных, смешанных и чистых сборок CLR.
Это зависит от ОС. В OS X есть заголовок в заголовке mach, который содержит начальный адрес для регистра EIP (указатель инструкции).
После загрузки двоичного файла ОС запускает выполнение с этого адреса:
кристи: тестовая ситуация $ otool -l ./a.out | grep -A 10 LC_UNIXTHREAD cmd LC_UNIXTHREAD cmdsize 80 аромат i386_THREAD_STATE считать i386_THREAD_STATE_COUNT [..] ss 0x00000000 eflags 0x00000000 eip 0x00001f8c cs 0x00000000 [..]
Адрес - это адрес функции запуска из двоичного файла:
кристи: тестовая ситуация $ nm ./a.out 0000200c D _NXArgc 00002008 D _NXArgv 00002000 D ___progname 00001fe0 т __dyld_func_lookup 00001000 A __mh_execute_header [..] 00001f8c T начало
В Mac OS X сначала вызывается функция «start», даже до «main»:
(GDB) б начало Точка останова 1 на 0x1f90 (gdb) b main Точка останова 2 на 0x1ff4 (GDB) R Запуск программы: /Users/diciu/Programming/test/a.out Чтение символов для разделяемых библиотек ++. сделанный Точка останова 1, 0x00001f90 в начале ()
Что касается окон, функции точки входа:
- Приставка:
void __cdecl mainCRTStartup( void ) {}
- GUI:
void __stdcall WinMainCRTStartup( void ) {}
- DLL:
BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL,DWORD fdwReason,void* lpReserved) {}
Единственная причина использовать их по сравнению с обычным main / WinMain / DllMain - это если вы хотите использовать свою собственную библиотеку времени выполнения (если вам нужен файл меньшего размера или пользовательские функции)
Для пользовательских реализаций времени выполнения и других приемов, чтобы получить меньшие PE-файлы, смотрите:
Если вас интересует книга, связанная с Windows и Win32 API, попробуйте
«Программирование приложений для Microsoft Windows» Джеффри Рихтера.