В программе на C / C ++ как система (windows, linux, mac OS X) вызывает функцию main () - PullRequest
16 голосов
/ 15 августа 2008

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

Ответы [ 7 ]

25 голосов
/ 15 августа 2008

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

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

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

8 голосов
/ 15 августа 2008

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

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

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

5 голосов
/ 29 августа 2008

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

  • Консоль: void __cdecl mainCRTStartup( void ) {}
  • GUI: void __stdcall WinMainCRTStartup( void ) {}
  • DLL: BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL,DWORD fdwReason,void* lpReserved) {}

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

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

1 голос
/ 27 августа 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 сначала вызывается функция «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 ()
1 голос
/ 15 августа 2008

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

0 голосов
/ 23 сентября 2008

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

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

0 голосов
/ 15 августа 2008

Вы можете посмотреть по следующим ссылкам:

...