Как вначале вызывается метод main () в C?

Как запускается C-программа?

51
задан ThinkingStiff 29 June 2012 в 17:40
поделиться

6 ответов

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

Некоторые детали (связанные с Windows): В PE файле есть заголовок IMAGE_OPTIONAL_HEADER, который имеет поле AddressOfEntryPoint, которое в свою очередь является адресом первого байта кода в файле, который будет выполнен.

24
ответ дан 7 November 2019 в 10:05
поделиться

Обратите внимание, что в дополнение к уже опубликованным ответам вы также можете сами позвонить по main . Обычно это плохая идея, зарезервированная для обфусцированного кода.

4
ответ дан 7 November 2019 в 10:05
поделиться

Операционная система вызывает функцию main(). На самом деле, обычно она вызывает что-то другое с таким странным названием, как _init. Компилятор C подключает к каждому приложению стандартную библиотеку, которая обеспечивает эту определенную операционной системой точку входа, а затем вызывает main().

Редактировать: Очевидно, что для некоторых это было недостаточно подробно и правильно.

Формат Executable and Linkable Format (ELF), который используют многие ОС Unix, определяет адрес точки входа. Это место, где программа начинает выполняться после того, как ОС завершает вызов exec(). В системе Linux это _init.

Из objdump -d:

Disassembly of section .init:

08049f08 <_init>:
 8049f08:       55                      push   %ebp
 8049f09:       89 e5                   mov    %esp,%ebp
 8049f0b:       83 ec 08                sub    $0x8,%esp
 8049f0e:       e8 a1 05 00 00          call   804a4b4 <call_gmon_start>
 8049f13:       e8 f8 05 00 00          call   804a510 <frame_dummy>
 8049f18:       e8 d3 50 00 00          call   804eff0 <__do_global_ctors_aux>
 8049f1d:       c9                      leave  
 8049f1e:       c3                      ret    

Из readelf -d:

 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000c (INIT)                       0x8049f08
 0x0000000d (FINI)                       0x804f018
 0x00000004 (HASH)                       0x8048168
 0x00000005 (STRTAB)                     0x8048d8c
 0x00000006 (SYMTAB)                     0x804867c
 0x0000000a (STRSZ)                      3313 (bytes)
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000015 (DEBUG)                      0x0
 0x00000003 (PLTGOT)                     0x8059114
 0x00000002 (PLTRELSZ)                   688 (bytes)
 0x00000014 (PLTREL)                     REL
 0x00000017 (JMPREL)                     0x8049c58
 0x00000011 (REL)                        0x8049be0
 0x00000012 (RELSZ)                      120 (bytes)
 0x00000013 (RELENT)                     8 (bytes)
 0x6ffffffe (VERNEED)                    0x8049b60
 0x6fffffff (VERNEEDNUM)                 3
 0x6ffffff0 (VERSYM)                     0x8049a7e
 0x00000000 (NULL)                       0x0

Видно, что INIT равен адресу _init.

Код для frame_dummy и __do_global_ctors_aux находится в наборе файлов с именами crtbegin.o и crtend.o (и вариантами этих имен). Они являются частью GCC. Этот код выполняет различные действия, необходимые для программы на языке Си, такие как установка stdin, stdout, глобальных и статических переменных и других вещей.

Следующая статья довольно хорошо описывает, что он делает в Linux (взято из ответа ниже с меньшим количеством голосов): http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html

Я считаю, что в чьем-то ответе уже описано, что делает Windows.

48
ответ дан 7 November 2019 в 10:05
поделиться

Операционная система вызывает функцию, включенную в среду выполнения C (CRT) и связанную с вашим исполняемым файлом. Это называется "CRT main."

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

Функция main CRT в Visual C++ делает еще несколько вещей, если мне не изменяет память. Он настраивает распределитель памяти, что важно при использовании Debug CRT для поиска утечек памяти или плохих доступов. Он также вызывает main внутри структурированного обработчика исключений, который отлавливает неудачные обращения к памяти и другие сбои и отображает их.

5
ответ дан 7 November 2019 в 10:05
поделиться

Операционная система вызывает main. В перемещаемом исполняемом файле будет адрес, указывающий на местоположение main (см. Unix ABI для получения дополнительной информации).

Но, кто вызывает операционную систему?

Центральный процессор, по сигналу "RESET" (который также подается при включении питания), начнет искать в ПЗУ по заданному адресу (скажем, 0xffff) свои инструкции.

Как правило, это будет своего рода инструкция перехода в BIOS, которая настраивает микросхемы памяти, загружает основные драйверы жесткого диска и т. д. и т. п. Затем считывается загрузочный сектор жесткого диска и запускается следующий загрузчик, который загружает файл, содержащий основную информацию о том, как читать, скажем, NTFS-раздел и как читать сам файл ядра. Будет настроено окружение ядра, загружено ядро, а затем - а затем! - ядро будет запущено на выполнение.

После того как вся эта тяжелая работа проделана, ядро может приступить к загрузке нашего программного обеспечения.

7
ответ дан 7 November 2019 в 10:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: