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

Я ищу более техническое объяснение, чем ОС вызывает функцию.

Может ли кто-нибудь помочь мне или указать мне на веб-сайт или книгу?


person Community    schedule 15.08.2008    source источник
comment
Кто проголосовал за закрытие? Этот вопрос кажется мне совершенно справедливым. Это хороший вопрос!!!   -  person Destructor    schedule 23.12.2016
comment
Я голосую за то, чтобы закрыть этот вопрос, потому что он Поиск рекомендаций по книгам, инструментам, программным библиотекам и т. д.: этот вопрос, скорее всего, приведет к ответам, основанным на мнении.   -  person Nimantha    schedule 17.06.2021


Ответы (5)


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

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

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

person Will Dean    schedule 15.08.2008

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

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

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

person Vincent Robert    schedule 15.08.2008

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

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

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

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

person Anders    schedule 28.08.2008


Это зависит от ОС. В OS X в заголовке mach есть кадр, который содержит начальный адрес для регистра 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 первой вызывается функция «старт», даже до «основной» функции:

(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 ()
person diciu    schedule 27.08.2008