Wie ruft das System (Windows, Linux und Mac OS X) in einem C/C++-Programm die Funktion main() auf?

Lesezeit: 3 Minuten

Ich suche nach einer technischeren Erklärung, als das Betriebssystem die Funktion aufruft.

Gibt es eine Website oder ein Buch?

Benutzer-Avatar
Will Dekan

Die .exe-Datei (oder eine entsprechende Datei auf anderen Plattformen) enthält eine „Einstiegspunkt“-Adresse. In erster Näherung lädt das Betriebssystem die relevanten Abschnitte der EXE-Datei in den Arbeitsspeicher und springt dann zum Einstiegspunkt.

Wie andere gesagt haben, wird dieser Einstiegspunkt nicht “main”, sondern Teil der Laufzeitbibliothek sein – er wird Dinge wie das Initialisieren statischer Objekte, das Einrichten der Argc und argv Parameter, Einrichten von Standardeingabe, Standardausgabe, Standardfehler usw. Wenn das alles erledigt ist, wird Ihre main()-Funktion aufgerufen. Wenn main beendet wird, durchläuft die Laufzeit einen analogen Prozess, bei dem Ihr Rückgabecode an die Umgebung zurückgegeben wird, statische Destruktoren aufgerufen werden, _atexit-Routinen aufgerufen werden usw.

Wenn Sie Microsoft-Tools haben (vielleicht nicht die Freebie-Tools), dann haben Sie alle Laufzeitquellen, und eine einfache Möglichkeit, sie zu betrachten, besteht darin, einen Haltepunkt auf die schließende Klammer Ihrer main() -Methode zu setzen und einen einzelnen Schritt zurückzugehen in die Laufzeit.

main() ist Teil der C-Bibliothek und keine Systemfunktion. Ich weiß nicht für OS X oder Linux, aber Windows startet normalerweise ein Programm mit WinMainCRTStartup(). Dieses Symbol initialisiert Ihren Prozess, extrahiert Befehlszeilenargumente und Umgebung (argc, argv, end) und Anrufe main(). Es ist auch dafür verantwortlich, Code aufzurufen, der danach ausgeführt werden soll main()wie atexit().

Wenn Sie in Ihrer Visual Studio-Datei nachsehen, sollten Sie in der Lage sein, die Standardimplementierung von zu finden WinMainCRTStartup um zu sehen, was es tut.

Sie können auch eine eigene Funktion definieren, die beim Start aufgerufen wird, indem Sie den “Einstiegspunkt” in den Linker-Optionen ändern. Dies ist oft eine Funktion, die keine Argumente akzeptiert und eine Leere zurückgibt.

Benutzer-Avatar
Anders

In Bezug auf Windows sind die Einstiegspunktfunktionen:

  • Konsole: void __cdecl mainCRTStartup( void ) {}
  • GUI: void __stdcall WinMainCRTStartup( void ) {}
  • DLL: BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL,DWORD fdwReason,void* lpReserved) {}

Der einzige Grund, diese über die normalen zu verwenden hauptsächlich, WinMainund DllMain wenn Sie Ihre eigene Laufzeitbibliothek verwenden möchten. (Wenn Sie eine kleinere Dateigröße oder benutzerdefinierte Funktionen wünschen.)

Für benutzerdefinierte Laufzeitimplementierungen und andere Tricks, um kleinere PE-Dateien zu erhalten, siehe:

  • Drei der vier Links sind defekt (nur Das Code-Projekt Link funktioniert). Z.B, “Es tut uns leid, die von Ihnen angeforderte Seite kann nicht gefunden werden.”“404” und “Hmm. Wir haben Probleme, diese Seite zu finden. Wir können keine Verbindung zum Server unter www.hailstorm.net herstellen.”.

    – Peter Mortensen

    27. Juni um 21:13 Uhr

  • @PeterMortensen Ja, 14 Jahre später neigen Links dazu, zu brechen. Jetzt behoben.

    – Anders

    27. Juni um 21:34 Uhr


Es ist OS-abhängig. In OS X gibt es einen Frame im Mach-Header, der die Startadresse für das EIP-Register (Instruction Pointer) enthält.

Sobald die Binärdatei geladen ist, startet das Betriebssystem die Ausführung von dieser Adresse:

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
[..]

Die Adresse ist die Adresse der “Start”-Funktion aus der Binärdatei:

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

In Mac OS X wird die „start“-Funktion zuerst aufgerufen, noch vor der „main“-Funktion:

(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 ()

Experte C++/CLI (siehe Seite 279) enthält sehr spezifische Details zu den verschiedenen Bootstrap-Szenarien für native, gemischte und reine CLR-Assemblys.

1216540cookie-checkWie ruft das System (Windows, Linux und Mac OS X) in einem C/C++-Programm die Funktion main() auf?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy