Как система (Windows, Linux, Mac OS X) вызывает функцию main() в программе C/C++?

StackOverflow https://stackoverflow.com/questions/12332

  •  08-06-2019
  •  | 
  •  

Вопрос

Я ищу более техническое объяснение, чем ОС вызывает функцию.Может ли кто-нибудь мне помочь или указать на веб-сайт или книгу?

Это было полезно?

Решение

Файл .exe (или его эквивалент на других платформах) содержит адрес «точки входа».В первом приближении ОС загружает соответствующие разделы файла .EXE в оперативную память, а затем переходит к точке входа.

Как говорили другие, эта точка входа не будет «основной», а будет частью библиотеки времени выполнения — она будет выполнять такие действия, как инициализация статических объектов, настройка параметров argc/argv, настройка stdin/stdout/stderr. , и т. д.Когда все это будет сделано, он вызовет вашу функцию main().При выходе из main среда выполнения выполняет аналогичный процесс передачи вашего кода возврата обратно в среду, вызова статических деструкторов, вызова подпрограмм _atexit и т. д.

Если у вас есть инструменты MS (возможно, не бесплатные), то у вас есть весь исходный код среды выполнения, и простой способ просмотреть его — поставить точку останова на закрывающую скобку вашего метода main() и выполнить один шаг назад. во время выполнения.

Другие советы

main() является частью библиотеки C и не является системной функцией.Я не знаю, для OS X или Linux, но Windows обычно запускает программу с WinMainCRTStartup().Этот символ запускает ваш процесс, извлекает аргументы командной строки и среду (argc, argv, end) и звонки main().Он также отвечает за вызов любого кода, который должен выполняться после main(), нравиться atexit().

Просматривая файл Visual Studio, вы сможете найти реализацию по умолчанию. WinMainCRTStartup чтобы увидеть, что он делает.

Вы также можете определить собственную функцию для вызова при запуске, это делается путем изменения «точки входа» в параметрах компоновщика.Часто это функция, которая не принимает аргументов и возвращает пустое значение.

Что касается окон, функции точки входа:

  • Консоль: void __cdecl mainCRTStartup( void ) {}
  • Графический интерфейс: void __stdcall WinMainCRTStartup( void ) {}
  • ДЛЛ: BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL,DWORD fdwReason,void* lpReserved) {}

Единственная причина использовать их вместо обычного main/WinMain/DllMain — это если вы хотите использовать свою собственную библиотеку времени выполнения (если вам нужен файл меньшего размера или пользовательские функции)

О пользовательских реализациях времени выполнения и других приемах получения PE-файлов меньшего размера см.:

Эксперт C++/CLI (см. стр. 279) содержит очень подробные сведения о различных сценариях начальной загрузки для собственных, смешанных и чистых сборок CLR.

Это зависит от ОС.В OS X в мах-заголовке есть кадр, содержащий начальный адрес регистра EIP (указатель инструкций).

После загрузки двоичного файла ОС запускает выполнение с этого адреса:

cristi:test diciu$ otool -l ./a.out | grep -A 10 LC_UNIXTHREAD
        cmd LC_UNIXTHREAD
    cmdsize 80
     flavor i386_THREAD_STATE
      count i386_THREAD_STATE_COUNT
[..]
        ss  0x00000000 eflags 0x00000000 eip 0x00001f8c cs  0x00000000
[..]

Адрес — это адрес функции «старт» из двоичного файла:

cristi:test diciu$ nm ./a.out
0000200c D _NXArgc
00002008 D _NXArgv
00002000 D ___progname
00001fe0 t __dyld_func_lookup
00001000 A __mh_execute_header
[..]
00001f8c T start

В Mac OS X первой вызывается функция «start», даже до «main» функции:

(gdb) b start
Breakpoint 1 at 0x1f90
(gdb) b main
Breakpoint 2 at 0x1ff4
(gdb) r
Starting program: /Users/diciu/Programming/test/a.out 
Reading symbols for shared libraries ++. done

Breakpoint 1, 0x00001f90 in start ()

Если вас интересует книга, посвященная Windows и Win32 API, попробуйте

«Программирование приложений для Microsoft Windows» Джеффри Рихтера.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top