29 Stimmen

Warum hat dieser Code noch funktioniert?

Ein alter Code, auf den ich gerade gestoßen bin:

MLIST * new_mlist_link()
{
    MLIST *new_link = (MLIST * ) malloc(sizeof(MLIST));
    new_link->next  = NULL;
    new_link->mapi  = NULL;
    new_link->result = 0;
}

Dies wurde aufgerufen, um eine verkettete Liste zu erstellen, aber ich habe bemerkt, dass es keine Anweisung gibt:

return new_link;

Auch ohne die Rückgabeanweisung wurde die Liste dennoch richtig erstellt. Warum ist das passiert?

Bearbeitung: Plattform: Mandriva 2009 64bit Linux 2.6.24.7-server GCC 4.2.3-6mnb1

Bearbeitung: Lustig... dieser Code lief auch erfolgreich auf etwa 5 verschiedenen Linux-Installationen, alle unterschiedliche Versionen/Varianten, sowie auf einem Mac.

35voto

Aric TenEyck Punkte 7792

Auf 32-Bit-Windows wird der Rückgabewert einer Funktion normalerweise im EAX-Register belassen. Ähnliche Setups werden in anderen Betriebssystemen verwendet, obwohl es natürlich vom Compiler abhängig ist. Diese bestimmte Funktion hat anscheinend die new_link-Variable an derselben Stelle gespeichert, sodass beim Rückkehren ohne Rückgabewert die Variable an dieser Stelle vom Aufrufer als Rückgabewert behandelt wurde.

Dies ist nicht tragbar und sehr gefährlich, aber es gehört auch zu den kleinen Dingen, die das Programmieren in C so viel Spaß machen.

7voto

in70x Punkte 1128

Möglicherweise wurde einfach der EAX-Register verwendet, der normalerweise den Rückgabewert der zuletzt aufgerufenen Funktion speichert. Das ist überhaupt keine gute Praxis! Das Verhalten für diese Art von Dingen ist undefiniert... Aber es ist cool zu sehen, wie es funktioniert ;-)

5voto

WhirlWind Punkte 13556

Es ist im Grunde Glück; anscheinend fügt der Compiler new_link genau an die Stelle ein, an der er einen Rückgabewert einfügen würde.

5voto

Georg Fritzsche Punkte 95256

Um dieses Problem zu vermeiden, verwenden Sie:

-Wreturn-type:

Warnen, wenn eine Funktion mit einem Rückgabetyp definiert ist, der standardmäßig int ist. Warnen Sie auch über eine Rückgabeanweisung ohne Rückgabewert in einer Funktion, deren Rückgabetyp nicht void ist (das Verlassen des Funktionskörpers am Ende wird als Rückgabe ohne Wert betrachtet), und über eine Rückgabeanweisung mit einem Ausdruck in einer Funktion, deren Rückgabetyp void ist.

-Werror=return-type um das obige in einen Fehler umzuwandeln:

Machen Sie die angegebene Warnung zu einem Fehler. Der Spezifikator für eine Warnung wird angehängt, zum Beispiel -Werror=switch verwandelt die von -Wswitch kontrollierten Warnungen in Fehler. Dieser Schalter hat eine negative Form, die verwendet wird, um -Werror für spezifische Warnungen aufzuheben, zum Beispiel -Wno-error=switch macht -Wswitch Warnungen nicht zu Fehlern, auch wenn -Werror in Kraft ist. Sie können die Option -fdiagnostics-show-option verwenden, um jede steuerbare Warnung mit der Option, die sie kontrolliert, zu versehen, um zu bestimmen, was mit dieser Option verwendet werden soll.

(aus GCCs Warnoptionen)

1voto

Dies funktioniert rein zufällig. Du solltest dich nicht darauf verlassen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X