2015-02-12 11 views
8

Was ist, wenn ich main als Referenz für die Funktion definiere?C++ "Haupt" als Referenz für die Funktion angeben?

#include<iostream> 
#include<cstring> 

using namespace std; 

int main1() 
{ 
    cout << "Hello World from main1 function!" << endl; 
    return 0; 
} 

int (&main)() = main1; 

Was wird passieren? Getestet habe ich in einem Online-Compiler mit Fehler "Segmentation fault":

here

Und unter VC++ 2013 wird es ein Programm abstürzt zur Laufzeit erstellt!

Ein Code, der die Daten des Funktionszeigers als Code aufruft, wird kompiliert, der beim Start sofort abstürzt.

Ich möchte auch ein ISO C++ Standard-Zitat darüber.

wird das Konzept sinnvoll sein, wenn Sie entweder von zwei Einstiegspunkte in Abhängigkeit von einigen Makro wie folgt definieren wollen:

int main1(); 

int main2(); 

#ifdef _0_ENTRY 
int (&main)() = main1; 
#else 
int (&main)() = main2; 
#endif 
+0

_ "Was wird passieren? Ich habe in einem Online-Compiler mit Fehler 'Segmentierung Fehler' getestet" _ Sie haben gerade Ihre eigene Frage beantwortet, nicht wahr? –

+0

Sie schließen freistehende Implementierungen aus, korrekt? –

+0

Es ist kein ISO C++ Standard Zitat, aber http://en.cppreference.com/w/cpp/language/main_function ist normalerweise ziemlich genau. Es besagt speziell, dass main eine spezielle Funktion ist und eine dieser "speziellen" Eigenschaften ist, dass die Adresse nicht vergeben werden kann. – qeadz

Antwort

16

das kein konformes C++ Programm ist. C++ erfordert, dass (Abschnitt 3.6.1)

Ein Programm wird eine globale Funktion main

Ihr Programm enthält eine globale nicht-a-Funktion main genannt enthalten genannt, die mit der einen Namenskonflikt führt main Funktion, die erforderlich ist.


Eine Begründung dafür wäre es die gehosteten Umgebung ermöglicht beim Programmstart zu, einen Funktionsaufruf zu main machen. Es entspricht nicht der Quellzeichenfolge main(args), bei der es sich um einen Funktionsaufruf, eine Funktionszeiger-Dereferenzierung, die Verwendung von operator() für ein Funktionsobjekt oder den Aufbau einer Instanz eines Typs main handeln könnte. Nein, main muss eine Funktion sein.

Eine zusätzliche Sache zu beachten ist, dass der C++ Standard nie sagt, was der Typ von main tatsächlich ist, und verhindert, dass Sie es beobachten. So können Implementierungen die Signatur neu schreiben (und tun!), Indem Sie z. B. eine von int argc, char** argv, char** envp hinzufügen, die Sie weggelassen haben. Offensichtlich konnte es das nicht für Ihre main1 und main2 tun.

+1

Ihr Angebot ist unvollständig. Unmittelbar danach heißt es _ "Es ist implementation-defined, ob ein Programm in einer freistehenden Umgebung eine Hauptfunktion definieren muss." _ Und es gibt keine Regel, dass ein solches Programm keine andere Art von Entitäten im globalen Namensraum namens 'main definieren kann '(p3:" Ein Programm, das main als gelöscht definiert oder das main als inline, static oder consxpr deklariert, ist unkorrekt. Der Name main ist nicht anderweitig reserviert. [Beispiel: member functions, classes und enumerations können als main bezeichnet werden. ebenso wie Entitäten in anderen Namespaces. -end Beispiel) "). –

+0

Ich denke, wir können davon ausgehen, dass das OP keine solche Implementierung verwendet. :) Aber vielleicht würde all dies diese Antwort verbessern? –

+0

@LightnessRacesinOrbit: Es ist interessant, dass sie beschlossen haben, diese Regel als universelle Aussage zu schreiben, gefolgt von einem Widerspruch, ohne auch nur ein "außer". Es wäre sicherlich nicht schwierig gewesen zu sagen "Ein Programm in einer gehosteten Umgebung sollte eine globale Funktion namens' main' enthalten oder "Ein Programm soll eine globale Funktion namens' main' enthalten, außer dass es sich in einer freistehenden Umgebung um eine Implementierung handelt -defined ... " –

7

wäre dieser nützlich, wenn Sie entweder von zwei Einstiegspunkte in Abhängigkeit von einigen Makro

Nein, nicht wirklich definieren wollen. Sie sollten dies tun:

int main1(); 
int main2(); 

#ifdef _0_ENTRY 
    int main() { return main1(); } 
#else 
    int main() { return main2(); } 
#endif 
+0

Ja, aber nur eine Funktionsreferenz zuzuweisen scheint für mich zumindest intuitiver. Ansonsten definieren wir eine andere Funktion, die nicht genau das ist, was ich möchte. – AnArrayOfFunctions

+2

Das ist eine nette und unaufdringliche Lösung. –

+0

@FISOCPP: Ich verstehe wirklich nicht warum nicht. Außerdem hast du keine Wahl. :) –

3

Dieser wird bald klar geworden schlecht gebildet, dank der Auflösung von CWG issue 1886, die derzeit in „versuchsweise bereit“ Status, der unter anderem die folgenden auf [Grund fügt .Anfang.main]:

Ein Programm, das eine variable main im globalen Bereich erklärt oder dass erklärt den Namen main mit Verknüpfung der Sprache C (in jedem Namespace) ist schlecht ausgebildet.

+0

Vielleicht sollten sie besser "Haupt" -Funktion Referenzen als Ausnahme von der Regel. – AnArrayOfFunctions

+3

@ FISOCPP: Das wäre zu komplex zu implementieren. 'main' muss eine einfache Funktion sein, die von der C++ - Laufzeit aufgerufen werden kann. Introducing Komplexitäten, wie Sie vorschlagen, ist es nicht wert. –

+0

@ T.C. Gut zu wissen, danke! –

1

Was in der Praxis passiert, hängt stark von der Implementierung ab.

In Ihrem Fall implementiert Ihr Compiler diese Referenz anscheinend als "verdeckter Zeiger". Zusätzlich dazu hat der Zeiger eine externe Verknüpfung. I.e. Ihr Programm exportiert ein externes Symbol namens main, das tatsächlich mit dem Speicherort im Datensegment verknüpft ist, das von einem Zeiger belegt wird. Der Linker zeichnet, ohne zu viel hineinzuschauen, den Speicherort als Eingangspunkt des Programms auf.

Wenn Sie später versuchen, diesen Speicherort als Einstiegspunkt zu verwenden, wird ein Segmentierungsfehler verursacht. Erstens gibt es an diesem Ort keinen sinnvollen Code. Zweitens kann ein bloßer Versuch, die Kontrolle an einen Ort innerhalb eines Datensegments zu übergeben, die "Datenausführungsschutzmechanismen" Ihrer Plattform auslösen.

Dadurch hofften Sie anscheinend, dass die Referenz optimiert wird, d. H. Dass main nur ein anderer Name für main1 wird. In deinem Fall ist es nicht passiert. Die Referenz überlebte als unabhängiges äußeres Objekt.

0

Sieht aus, als ob Sie bereits die Frage beantwortet haben, was passiert.

Soweit warum, in Ihrem Code main ist ein Verweis/Zeiger auf eine Funktion. Das ist anders als eine Funktion. Und ich würde einen Segmentfehler erwarten, wenn der Code einen Zeiger anstelle einer Funktion aufruft.