Warum gibt es keinen Compilerfehler, wenn keine return-Anweisung vorhanden ist?

Lesezeit: 7 Minuten

Benutzeravatar von iammilind
iammilind

Im Gegensatz zu Java gilt in C/C++ Folgendes erlaubt:

int* foo ()
{
  if(x)
    return p;

  // What if control reaches here?
}

Dies führt häufig zu Abstürzen und es ist schwierig, Probleme zu debuggen. Warum nicht die Standard erzwingen, a zu haben endgültige Rückkehr für Nicht-void Funktionen? (Compiler generieren einen Fehler für eine falsche return Wert.)

Gibt es ein Flag in GCC bzw MSVC um dies durchzusetzen? (etwas wie -Wunused-result)

  • Die folgende Botschaft zum Mitnehmen lautet: Wenn Sie diese Art von Überprüfungen wünschen, verwenden Sie -Wall auf gcc und eine hohe Warnstufe (3 oder 4) in Visual Studio.

    – TJ Crowder

    7. Juni 2011 um 5:58 Uhr


  • Ich habe lange nach einem Compiler-Flag gesucht, das dazu führen würde, dass alle Funktionen vorhanden sind throw "LOL Y U HERE??"; am Ende von ihnen. Das Verhalten ist undefiniert, also kann alles passieren, und das Auslösen einer Ausnahme gilt sicherlich als alles. Nur zu Testzwecken; Ich wäre damit einverstanden, wenn sie in der Veröffentlichung optimiert werden.

    – Dennis Zickefoose

    7. Juni 2011 um 6:23 Uhr

  • Es ist nicht undefiniert ob x ist deklariert const bool x = true;.

    – Bo Persson

    7. Juni 2011 um 7:41 Uhr

  • @Dennis: IIRC, das am Ende einer Funktion ausgeführt wird, ist nicht UB, es sei denn, der Aufrufer versucht, den Rückgabewert zu verwenden.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    7. Juni 2011 um 15:13 Uhr

  • Schlechter Stil und UB sind verschieden.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    7. Juni 2011 um 18:50 Uhr

Es ist nicht erlaubt (undefiniertes Verhalten). Allerdings verlangt die Norm in diesem Fall keine Diagnostik.

Der Standard verlangt nicht, dass die letzte Anweisung lautet return wegen Code wie diesem:

while (true) {
  if (condition) return 0;
}

Dies gibt immer 0 zurück, aber ein dummer Compiler kann es nicht sehen. Beachten Sie, dass der Standard keine intelligenten Compiler vorschreibt. EIN return Aussage nach der while block wäre eine Verschwendung, die ein dummer Compiler nicht optimieren könnte. Der Standard möchte nicht verlangen, dass der Programmierer verschwendeten Code schreibt, nur um einen dummen Compiler zufrieden zu stellen.

g++ -Wall ist intelligent genug, um eine Diagnose auf meinem Computer auszugeben.

  • “Beachten Sie, dass der Standard keine intelligenten Compiler vorschreibt.” +1.

    – atzol

    29. Juli 2016 um 18:22 Uhr

  • Ich denke, ein besseres Beispiel wäre so etwas wie: int test(...) { if (...) { [compute something and return it]; } else { log_something(...); FATAL_ERROR(); }; }. Wenn FATAL_ERROR() kann nicht zurückkehren, dann das Ende test() kann niemals erreicht werden, aber ein Compiler hätte normalerweise keine Möglichkeit, dies zu wissen.

    – Superkatze

    26. Juli 2018 um 20:28 Uhr

  • Dieser Code verursacht undefiniertes Verhalten, wenn die Bedingung falsch ist (kein Vorwärtsfortschritt)

    – MM

    17. September 2020 um 3:00 Uhr

  • @MM Dies ist kein wörtlicher Code. condition steht für einen beliebigen Ausdruck.

    – nm

    17. September 2020 um 6:38 Uhr

Benutzeravatar von Prinz John Wesley
Prinz John Wesley

Verwenden Sie die -Wand Flagge ein GCC.

Warnung: Die Steuerung erreicht das Ende der nicht ungültigen Funktion

Oder genauer gesagt, -Wreturn-Typ.

  • IIRC gcc diagnostiziert es nur, wenn Optimierungen aktiviert sind, da es die Kontrollflussanalyse verwendet, um es zu diagnostizieren, und das wird nicht ausgeführt, wenn es nicht optimiert wird.

    – Jan Hudec

    7. Juni 2011 um 5:44 Uhr

  • @ Tj Crowder: For C ++ , a function without return type always produces a diagnostic message, even when -Wno-return-type is specified. The only exceptions are main and functions defined in system headers – Aus gcc man Seite

    – Prinz John Wesley

    7. Juni 2011 um 5:54 Uhr


  • Interessant, gcc hat es nicht erkannt -Wall wenn ich es gemacht habe mainVerzweigung weiter argc. Aber es tat erkennen, wenn ich eine separate Funktion hinzugefügt und dort ausgeführt habe. main scheint ein Sonderfall zu sein (wie es in so vielerlei Hinsicht der Fall ist). Bearbeiten: @John: Überlappende Kommentare. 🙂

    – TJ Crowder

    7. Juni 2011 um 5:56 Uhr


  • @TJ main() muss nicht explizit enthalten return Wert; siehe auf der Website von Bjarne Stroustrup www2.research.att.com/~bs/bs_faq2.html#void-main

    – iammilind

    7. Juni 2011 um 6:31 Uhr


  • Es ist standardmäßig definiert, überprüfen Sie die Antwort des Shafik hier

    – r0n9

    19. Februar 2014 um 3:53 Uhr


Benutzeravatar von Xeo
Xeo

Meine Vermutung: Weil der Programmierer es manchmal besser weiß als der Compiler. Mit diesem einfachen Beispiel ist klar, dass etwas nicht stimmt, aber betrachten Sie einen Wechsel vieler Werte oder viele Überprüfungen im Allgemeinen. Sie als Programmierer kennt dass bestimmte Werte einfach nicht an die Funktion übergeben werden, der Compiler aber nicht und nur darauf hinweist, dass etwas nicht stimmen könnte.

#include <iostream>

int foo(){
    if(false)
        return 5;
}

int main(){
    int i = foo();
    std::cout << i;
}

Beachten Sie, dass sogar Warnstufe 1 auf MSVC gibt die folgende Warnung aus:

Warnung C4715: ‘foo’: Nicht alle Kontrollpfade geben einen Wert zurück

  • “Beachten Sie, dass sogar Warnstufe 1 auf MSVC die folgende Warnung ausgibt:” Das ist interessant. Das habe ich auch bei Level 4 mit VS 2005 nicht hinbekommen.

    – TJ Crowder

    7. Juni 2011 um 5:38 Uhr

  • @TJ: Laut MSDN sollte 2005 diese Warnung auch auf Stufe 1 ausgeben. Siehe den Link, den ich hinzugefügt habe.

    – Xeo

    7. Juni 2011 um 5:46 Uhr


  • @Xeo: Faszinierend. Ich erhalte den Fehler, wenn ich a hinzufüge foo funktionieren wie deine, aber nicht wenn ich genau dasselbe in der automatisch generierten mache _tmain Funktion; Beispiel. Die Hauptfunktion ist speziell (wie in so vielen Dingen).

    – TJ Crowder

    7. Juni 2011 um 5:53 Uhr


  • Kontrollflusswarnungen wie diese werden im Allgemeinen nur ausgegeben, wenn der Optimierer ausgeführt wird und Analysen durchführt. Sie sind also normalerweise nur im Einzelhandel erhältlich.

    – Martin Lovell

    7. Juni 2011 um 5:53 Uhr

  • @Beispiel: Das liegt daran, dass der Standard dies ausdrücklich zulässt main ohne return-Anweisung sein. Wenn es weggelassen wird, ist das Ergebnis so, als ob es gewesen wäre return 0; schlussendlich.

    – Xeo

    7. Juni 2011 um 6:06 Uhr

Benutzeravatar von Florian
Florian

Sie können die Warnung mithilfe der folgenden Compileroptionen in einen Fehler umwandeln

-Wreturn-type -Werror=return-type.

Schau dir das an Verknüpfung

Die offensichtliche Antwort ist: Weil es kein Fehler ist. Es ist nur ein Fehler, wenn
x falsch ist und der Aufrufer den Rückgabewert verwendet, beides kann zumindest im allgemeinen Fall nicht unbedingt vom Compiler bestimmt werden.

In diesem speziellen Fall (Rückgabe eines Zeigers) wäre es nicht allzu schwierig, a zu verlangen return für alle Pfade; Java tut dies. Im Allgemeinen ist es jedoch in C++ nicht sinnvoll, dies zu verlangen, da Sie in C++ benutzerdefinierte Typen zurückgeben können, für die es möglicherweise unmöglich ist, einen Wert zu konstruieren (kein Standardkonstruktor usw.). Wir haben also die Situation, in der der Programmierer möglicherweise nicht in der Lage sein, a bereitzustellen return
in einer Verzweigung, von der er oder sie weiß, dass sie nicht genommen werden kann, und der Compiler kann nicht feststellen, dass die Verzweigung nicht genommen werden kann.

Die meisten Compiler werden in solchen Fällen warnen, wenn sie den Fluss feststellen können. Alle, die ich gesehen habe, warnen jedoch auch in einigen Fällen, in denen es eindeutig unmöglich ist, vom Ende zu fallen. (Sowohl g++ als auch VC++ warnen vor:

int
bar( char ch )
{
    switch ( ch & 0xC0 ) {
    case 0x00:
    case 0x40:
        return 0;

    case 0x80:
        return -1;

    case 0xC0:
        return 1;
    }
}

, zumindest mit den üblichen Optionen. Obwohl es ziemlich klar ist, dass diese Funktion niemals am Ende abfällt.)

Benutzeravatar von Peter Mortensen
Peter Mortensen

Soweit ich mich erinnere, warnt Sie Visual Studio 2008 vor einem “Ausführungspfad, der keinen Rückgabewert hat”. Es ist im Sinne von “C++ wird Sie nicht davon abhalten, Ihnen ins Knie zu schießen” erlaubt. Sie müssen also denken, nicht der Compiler.

Benutzeravatar von sergio
sergio

Was der Standard über diese Art der Programmierung sagt, ist, dass sie produziert undefiniertes Verhalten.

Undefiniertes Verhalten ist Freude und Leid von C/C++, aber es ist auch ein grundlegendes Merkmal des Sprachdesigns, das viele der Low-Level-Optimierungen ermöglicht, die C zu einer Art “High-Level-Assembler” machen (das ist es eigentlich nicht , aber nur um Ihnen eine Idee zu geben).

Während ich also auf Johns Antwort über den Schalter zur Verwendung mit GCC umleite, möchte ich auf eine sehr interessante Analyse von undefiniertem Verhalten und all seinen Geheimnissen hinweisen, um zu wissen, “warum” der Standard dies nicht verhindert: Was jeder C-Programmierer über undefiniertes Verhalten wissen sollte. Es ist eine sehr lehrreiche Lektüre.

1433320cookie-checkWarum gibt es keinen Compilerfehler, wenn keine return-Anweisung vorhanden ist?

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

Privacy policy