Kompilieren und führen Sie das Programm ohne main() in C
Ich versuche zu kompilieren und führen Sie das folgende Programm ohne main()
Funktion in C
. Ich kompiliert habe mein Programm mit dem folgenden Befehl.
gcc -nostartfiles nomain.c
Und compiler gibt Warnung
/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000400340
Ok, Kein problem. dann habe ich ausführen ausführbare Datei (.out), beide printf
Aussagen erfolgreich drucken, und dann bekommen "segmentation fault".
So, meine Frage ist, Warum segmentation fault nach der erfolgreichen Ausführung der print-Anweisung?
mein code:
#include <stdio.h>
void nomain()
{
printf("Hello World...\n");
printf("Successfully run without main...\n");
}
Ausgabe:
Hello World...
Successfully run without main...
Segmentation fault (core dumped)
Hinweis:
Hier -nostartfiles
gcc-flag verhindert, dass der compiler mit standard-startup-Dateien als Verlinkung
Ich bin überrascht, dass dies überhaupt funktioniert. Ehrlich gesagt, halte ich diese Behandlung durch den linker werden fehlerhafte (oder zumindest eine Schlechte Sache): es wurde kein Eintrag-Punkt, so dass der linker nur halluzinierte er aus, was Funktion war sehr praktisch. Blech.
zumindest der linker war so freundlich genug, um die Aufmerksamkeit darauf lenken, mit einer Verwarnung und zu erklären, was Ausweichaktion war es! Du hast Recht, das könnte besser sein als ein Fehler, anstatt nur eine Warnung, obwohl.
Warum würden Sie verwenden keinen main?
Nicht übermäßig relevant zu einer Diskussion über UNIX-artigen Systemen, aber der Eintrag-Punkt für Windows-Programme ist nicht unbedingt
eigentlich sowohl auf Windows-und Linux-Sie können beliebigen Einstiegspunkt: für Linux ist
zumindest der linker war so freundlich genug, um die Aufmerksamkeit darauf lenken, mit einer Verwarnung und zu erklären, was Ausweichaktion war es! Du hast Recht, das könnte besser sein als ein Fehler, anstatt nur eine Warnung, obwohl.
Warum würden Sie verwenden keinen main?
Nicht übermäßig relevant zu einer Diskussion über UNIX-artigen Systemen, aber der Eintrag-Punkt für Windows-Programme ist nicht unbedingt
main
, aber WinMain
oder wWinMain
.eigentlich sowohl auf Windows-und Linux-Sie können beliebigen Einstiegspunkt: für Linux ist
ld
es wäre -e
option für den Windows-MSVC-linker, es wäre /ENTRY
option.InformationsquelleAutor msc | 2017-02-19
Du musst angemeldet sein, um einen Kommentar abzugeben.
Lassen Sie uns einen Blick auf die erzeugte Montage des Programms:
Hinweis: die
ret
- Anweisung. Ihr Programm-Einstiegspunkt wird bestimmtnomain
ist alles in Ordnung. Aber sobald die Funktion zurückkehrt, versucht er zu springen, in einer Adresse auf dem call-stack... das ist nicht ausgefüllt. Das ist ein illegaler Zugriff und ein "segmentation fault" folgt.Eine schnelle Lösung wäre zu nennen
exit()
am Ende des Programms (und vorausgesetzt, C11, wir könnten auch markieren die Funktion als_Noreturn
):In der Tat, jetzt ist deine Funktion verhält sich so ziemlich wie eine normale
main
Funktion, da nach der Rückkehr ausmain
, dieexit
Funktion wird aufgerufen mitmain
's Rückgabewert.Wir sind in der Tat. Obwohl der Weg in den OP vorgeschlagen, eine Unix-Variante. Das gepaart mit der Beliebtheit bestimmter Architekturen und Befehlssätze war der einzige Grund, warum ich fühlte mich zu präsentieren generierte assembly in der Antwort.
Nur eine Beobachtung.
-nostartfiles
können auch Rendern, der C-Bibliothek unbrauchbar. Ohne die C Systemstart ausgeführt nachfolgende Aufrufe der C library-Funktionen kann unerwartet fehlschlagen. Auf Linux, wenn Sie waren zu kompilieren mit-nostartupfiles
und-static
können Sie das Programm Schuld. Es gibt C Bibliotheken, wie MUSL, die nicht erfordern eine up-front-Initialisierung, die entworfen sind, um die Arbeit in diesem Umfeld.InformationsquelleAutor StoryTeller
In C, wenn Funktionen/Unterprogramme aufgerufen werden, die Stapel aufgefüllt (in der Reihenfolge):
main() als Startpunkt, ELF-Strukturen das Programm in einer Weise, dass alle Anweisungen kommt zuerst bekommen würde, schob zuerst, in diesem Fall printfs sind.
Nun, das Programm ist irgendwie abgeschnitten, ohne Rückkehr-Adresse ODER
__end__
und infact es wird davon ausgegangen, dass alles, was es auf dem stack an, dass(__end__
) Ort der return-Adresse, wird aber leider nicht und daher stürzt es ab.Das ist, warum ich erwähnt, ELF(executable and linkable format), das erzeugt wird durch das cross-kompilieren für eine bestimmte BOGEN-Typ auf das gewünschte OS.
Zu wählerisch sein, können Sie das ELF-format selbst bei Systemen, die mit keinen stack. Ein Beispiel eines solchen Systems ist in Freescale RS08 mit dem Codewarrior-compiler, erzeugt ELF-linker-Dateien.
InformationsquelleAutor Milind Deore