C ++ deklarieren Sie 'main' als Referenz für die Funktion?

8

Was ist, wenn ich main als Referenz für die Funktion definiere?

%Vor%

Was wird passieren? Ich habe in einem Online-Compiler mit dem Fehler "Segmentierungsfehler" getestet:

hier

Und unter VC ++ 2013 wird es ein Programm erstellen, das zur Laufzeit abstürzt!

Ein Code, der die Daten des Funktionszeigers als Code aufruft, wird kompiliert, was beim Start sofort zum Absturz führt.

Ich möchte auch ein ISO C ++ Standard-Zitat dazu.

Das Konzept wird nützlich sein, wenn Sie einen von zwei Eintrittspunkten abhängig von einem Makro wie diesem definieren wollen:

%Vor%     
AnArrayOfFunctions 12.02.2015, 18:00
quelle

5 Antworten

16

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

  

Ein Programm soll eine globale Funktion namens main

enthalten

Ihr Programm enthält eine globale Nicht-a-Funktion namens main , die einen Namenskonflikt mit der benötigten main -Funktion einführt.

Eine Begründung dafür wäre, dass die gehostete Umgebung während des Programmstarts einen Funktionsaufruf an main ausführen kann. Dies 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 des Typs main handeln könnte. Nein, main muss eine Funktion sein.

Eine zusätzliche Sache, die zu beachten ist, ist, dass der C ++ Standard nie sagt, was der Typ von main ist und verhindert, dass Sie ihn 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. Natürlich könnte es das nicht für deine main1 und main2 wissen.

    
Ben Voigt 12.02.2015, 18:04
quelle
7
  

Dies ist nützlich, wenn Sie abhängig von einem Makro einen der beiden Eingangspunkte definieren möchten.

Nein, nicht wirklich. Sie sollten dies tun:

%Vor%     
quelle
3

Dies wird bald klar geworden schlecht gebildet, dank der Auflösung von CWG-Ausgabe 1886 , derzeit im Status "vorläufig bereit", der unter [basic.start.main] unter anderem Folgendes hinzufügt:

  

Ein Programm, das eine Variable main im globalen Gültigkeitsbereich deklariert   deklariert den Namen main mit C-Sprachverknüpfung (in einem beliebigen Namespace)   schlecht gebildet.

    
T.C. 12.02.2015 18:12
quelle
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 Ort als Einstiegspunkt zu verwenden, wird der 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 Mechanismen zum Schutz der Datenausführung Ihrer Plattform auslösen.

Sie haben damit anscheinend gehofft, dass der Verweis 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 externes Objekt.

    
AnT 12.02.2015 18:13
quelle
0

Sieht so aus, als hätten Sie bereits die Frage beantwortet, was passiert.

Soweit wie, 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.

    
Jonathan Wood 12.02.2015 18:32
quelle