Frage

Gestern fand ich mich Code wie folgt zu schreiben:

SomeStruct getSomeStruct()
{
    SomeStruct input;

    cin >> input.x;
    cin >> input.y;
}

Natürlich vergessen, um tatsächlich die Struktur kehre ich gerade erstellt haben. Merkwürdigerweise sind die Werte in der Struktur, dass war zurückgegeben wurde durch diese Funktion auf Null initialisiert (wenn g kompiliert ++ verwendet das ist). Ist das nur ein Zufall oder hat ein Ein SomeStruct erstellt und initialisiert irgendwo implizit?

War es hilfreich?

Lösung

  

Hat ein Ein SomeStruct erstellt und irgendwo implizit initialisiert?

Denken Sie darüber nach, wie sich die Struktur zurückgeführt wird. Wenn beide x und y 32 Bits sind, ist es zu groß ist, in einem Register auf einer 32-Bit-Architektur zu passen, und das gleiche gilt für 64-Bit-Werte auf einer 64-Bit-Architektur (@Denton Gentry Antwort erwähnt, wie einfachere Werte zurück), so hat es irgendwo zugeordnet werden. Es wäre verschwenderisch den Heap für diesen Einsatz, so hat es auf dem Stack zugeordnet werden. Aber es kann nicht auf dem Stapelrahmen Ihrer getSomeStruct Funktion sein, denn das ist nicht gültig mehr, nachdem die Funktion zurückkehrt.

Der Compiler hat anstelle der Anrufer erzählt die aufgerufene Funktion, wo das Ergebnis setzen (die auf dem Stapel des Anrufers wahrscheinlich irgendwo ist), durch die gerufene Funktion einen verborgenen Zeiger auf den Raum zugeordnet vorbei. Also, wo der Platz es auf Null gesetzt wird, ist auf dem Anrufern , nicht auf Ihrer getSomeStruct Funktion.

Es gibt Optimierungen auch wie die „benannten Wert Rendite-Optimierung“, wo zusätzliche Kopien elided werden kann. So musste man die fehlende return verwendet, wäre das Ergebnis direkt auf die vom Anrufer zugewiesenen Raum geschaffen werden, statt eine temporäre Erstellen und Kopieren es.

Um mehr darüber zu wissen, was passiert ist, haben Sie bei der CLIP-Funktion zu suchen. Ist es zu initialisieren (auf Null) einem „leeren“ SomeStruct, auf die Sie später den Rückgabewert Ihrer getSomeStruct Funktion zuweisen? Oder tut es etwas anderes?

Andere Tipps

das Ende einer Funktion herunterfallen, die einen Wert zurückgeben (ohne explizit einen Wert zurückkehrt) führt zu undefinierten Folgen erklärt. Für gcc, sollten Sie mit der -Wall Befehlszeilenoption starten, der auf nützlichsten Warnungen dreht. Die spezifische gcc Warnung, dass die Warnung steuert Sie wollen, ist -Wreturn-type (die in -Wall enthalten ist, ich dies nur der Vollständigkeit halber erwähnt).

Sobald Sie Warnungen eingeschaltet, können Sie auch -Werror verwenden sollten Warnungen als Fehler zu behandeln und den Build-Stopp an der Stelle macht es einen Fehler erkennt.

Die Aufrufkonventionen für die meisten modernen CPU-Architekturen ein bestimmtes Register geben Sie eine Funktion Rückgabewert zurück an den Aufrufer übergeben. Der Anrufer macht den Funktionsaufruf, und dann verwendet die angegebenen Register als Rückgabewert. Wenn Sie nicht explizit einen Wert zurückgeben, wird dennoch der Anrufer verwenden, was Müll in diesem Register wird passiert.

Der Compiler wird auch alle Register verwendet es für die interne Berechnung innerhalb der Funktion zur Verfügung hat. Das Register zum Halten des Rückgabewertes bezeichnet wird auch für misc Berechnung innerhalb der Funktion verwendet werden. So, wenn Sie vergessen, einen Rückgabewert angeben, ist es nicht ungewöhnlich ist der richtige Wert zu finden ist wie durch ein Wunder an den Aufrufer zurückgegeben worden. Der Compiler verwendet das Melden Sie Ihr Objekt speichern

Leider auch eine triviale Änderung der Funktion kann die Registerzuweisung führen zu ändern, so dass der Rückgabewert wird wahr Müll.

Das finde ich interessant. Mit Standardoptionen verwendet, haben die folgenden Compiler das folgende Verhalten, wenn die GetSomeStruct() Funktion Kompilieren:

  • Microsoft VC, alle Versionen (seit VC6 sowieso):

    error C4716: 'getSomeStruct' : must return a value

  • Digital Mars:

    Warning 18: implied return of getSomeStruct at closing '}' does not return value

  • Comeau:

    warning: missing return statement at end of non-void function "getSomeStruct"

  • gcc:

    kein Fehler oder Warnung

In Anbetracht der folgenden zwei Sätze aus der Norm (6.6.3 Absatz 2):

  

Eine return-Anweisung ohne eine   Ausdruck kann nur verwendet werden, in   Funktionen, die keinen Wert zurückgeben,   das heißt, eine Funktion, mit der Rückkehr   Typ void, einen Konstruktor (12.1) oder eine   destructor (12.4). ... abfließende   das Ende einer Funktion entspricht   eine Rückkehr ohne Wert; dieses Ergebnis   in undefinierten Verhalten in einem   Wert-Rückkehr-Funktion.

Ich würde sagen, es gibt wenig Grund für einen Compiler keinen Fehler in diesem Fall zu geben. Warum haben so viele Compiler geben nur eine Warnung oder keine Diagnose überhaupt?

Für mich ist der Compiler hat es nicht zulassen, dass: http://codepad.org/KkzVCesh

Sie erhalten keine Warnung, weil Sie nicht haben -Wall -Werror eingeschaltet. (Wie in anderen Antworten angegeben)

Aber ich denke, Sie wahrscheinlich eine Null-gefüllte Struktur als Ergebnis bekommen, weil das Stack-Objekt standardmäßig in der CLIP-Funktion aufgebaut wurde, möglicherweise mit expliziten Null Argumenten, oder auch aufgrund Nullen auf dem Stack?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top