54 votes

En C, comment la méthode main () est-elle initialement appelée?

Comment un programme C commence-t-il?

49voto

Zan Lynx Points 23100

Le système d'exploitation appelle l' main() fonction. En fait, il appelle généralement quelque chose d'autre nommé une chose étrange comme _init. Le compilateur C, des liens, une bibliothèque standard de chaque application qui fournit ce système d'exploitation défini de point d'entrée, puis appelle main().

Edit: Évidemment, cela n'a pas été détaillée et correcte suffisant pour certaines personnes.

L' Exécutable et Linkable Format (ELF) laquelle de nombreux systèmes d'exploitation Unix utilisation définit un point d'entrée de l'adresse. C'est là que le programme commence à courir après les OS termine exec() appel. Sur un système Linux, c'est _init.

De 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    

De 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

Vous pouvez voir que INIT est égale à l'adresse de _init.

Le code pour frame_dummy et __ _ _ ne_global_ctors_aux est dans un ensemble de fichiers nommés crtbegin.o et crtend.o (et les variantes de ces noms). Ceux-ci font partie de la GCC. Ce code fait différentes choses nécessaires pour un programme C comme la mise en place de stdin, stdout, globales et variables statiques et d'autres choses.

Je crois que quelqu'un d'autre réponse déjà décrit ce que Windows ne.

24voto

Andrey Points 36869

Finalement, c'est le système d'exploitation. Il y a généralement un moyen entre le point d’entrée réel et la fonction principale, ceci est inséré par le compilateur.

Quelques détails (liés à Windows): Il existe un en-tête dans le fichier PE appelé IMAGE_OPTIONAL_HEADER qui contient le champ AddressOfEntryPoint , qui est à son tour l'adresse du premier octet de code du fichier qui sera réalisé.

9voto

7voto

Paul Nathan Points 22910

Les appels de système d'exploitation principal. Il y aura une adresse dans la transférable, l'exécutable qui pointe à l'emplacement de la main (Voir l'Unix ABI pour plus d'informations).

Mais, qui appelle le système d'exploitation?

L'unité centrale de traitement, sur le "RESET" du signal, (qui est aussi affirmé à la mise sous tension), va commencer à rechercher dans certaines ROM à une adresse donnée (disons, 0xffff) pour les instructions.

Typiquement, il y aura une sorte d'instruction de saut pour le BIOS, qui obtient les puces de mémoire configurée, la base sur disque dur pilotes chargés, etc, etc. Ensuite, le Secteur de Démarrage du disque dur est en lecture, et la prochaine bootloader est lancée, qui charge le fichier contenant les informations de base sur la façon de lire, par exemple, une partition NTFS et comment lire le fichier du noyau lui-même. Le noyau de l'environnement sera mis en place, le noyau chargé, et puis et puis! - le noyau sera sauté à l'exécution.

Après tout ce dur travail a été fait, le noyau peut alors procéder à la charge de notre logiciel.

5voto

Drew Hoskins Points 3206

Le système d'exploitation appelle une fonction incluse dans le runtime C (CRT) et lié à votre exécutable. Appelons cela "CRT principal."

CRT principal fait un peu les choses, les deux plus importantes, au moins en C++, il est exécuté à travers un tableau global des classes C++ et appel à leurs constructeurs, et d'appeler votre fonction main() et donner sa valeur de retour de la coquille.

Le Visual C++ CRT principal fait un peu plus de choses, si ma mémoire est bonne. Il configure l'allocateur de mémoire, important si vous utilisez le Débogage CRT pour aider à trouver des fuites de mémoire ou de mauvaise accès. Il appelle également principal au sein d'une exception structurée gestionnaire de captures mauvais accès à la mémoire et autres plantages et les affiche.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X