| 

.NET C# Java Javascript Exception

9
Hallo,
kann mir jemand sagen, warum C++ diesen Code ausführt, bzw. die Methode Fahren() korrekt aufruft?
Nach allen bekannten Regeln der Programmierung muss es doch beim Aufruf von
a->Fahren()

eine Null-Pointer-Fehler geben weil a auf NULL steht bzw. sogar deleted wurde.

CAuto*a = new CAuto();

a=NULL;
delete a;

a->Fahren(); //Warum kracht es hier nicht????


Ich nutze Visual Studio 2010 als Compilter / Editor.

Hier der volle Code:

KLASSE:

#include <iostream>
#include <string>

using namespace std;

class CAuto
{
public:
void Fahren()
{
cout<<"Ich fahre.."<<endl;
}

};


Main:
include "CAuto.cpp"

void main()
{
CAuto *a = new CAuto();
a=NULL; //Diese NULL-Zuweisung kann auch weggelassen werden...
delete a;

a->Fahren(); //Warum kracht es hier nicht????

cin.get();
}
News:
05.11.2012
Maik_1978 664 1 8
+1 für diese lehrreiche Nuß. Aber sag mal: 21 Fragen, davon 19 beantwortete - und erst eine Bewertung? Weißt Du, wozu die Pfeile und grünen Häkchen neben den Antworten gut sind?
Matthias Hlawatsch 05.11.2012
1 Antwort
6
Da fallen mir zwei mögliche Erklärungen ein:

  • Es ist zwei Stunden nach Feierabend und a ist doch nicht NULL.
  • Du hast mit dem Debugger ganz genau hingeschaut, a ist wirklich NULL, aber Fahren ist eine statische Methode. Der Compiler sollte Dir dann aber wenigstens eine Warnung anzeigen.


Update:
OK, das war es also nicht. Dann wäre zumindest noch festzuhalten, dass das Objekt, das Du am Anfang erzeugst, nicht gelöscht wird - Du löschst nur einen NULL-Pointer, und Dein Code hat ein Speicherleck. Evtl. (Spekulation, da steck ich jetzt nicht so tief drin) hat der Compiler die beiden Zeilen nach dem new einfach wegoptimiert, weil sie eh nichts bewirken, oder es passiert irgendwas anderes, das dazu führt, dass am Ende doch Fahren() auf dem mit new erzeugten Objekt aufgerufen wird. Lass doch mal die Zuweisung von NULL weg und schau, was dann passiert.

Update 2:
OMG...
Ich kann es reproduzieren.
Willkommen in der Hölle der C++-Sprachspezifikation (anders kann ich es nicht nennen, grusel...). Schau Dir mal diese Frage bei stackoverflow an. Wenn ich das richtig verstehe, so ist es undefined, was beim Aufruf von Fahren() über einen NULL-Pointer passiert. Der C++-Compiler von VS scheint die Methode halt einfach trotzdem aufzurufen (wobei der this-Pointer dann auf NULL zeigt), und da sie zwar nicht statisch definiert ist, es de facto aber ist (es wird auf keinen Member zugegriffen), läuft der Code durch. Sobald Du CAuto um ein Feld ergänzt und in Fahren() darauf zugreifst, bekommst Du den erwarteten Fehler. Und ebenso, wenn Du Fahren() als virtual deklarierst. Siehe dazu auch die Antwort von Mark Ransom in dem oben verlinkten SO-Thread:
You might think that calling a function on an object pointer will dereference the pointer and cause UB. In practice if the function isn't virtual, the compiler will have converted it to a plain function call passing the pointer as the first parameter this, bypassing the dereference and creating a time bomb for the called member function. If the member function doesn't reference any member variables or virtual functions, it might actually succeed without error. Remember that succeeding falls within the universe of "undefined"!
05.11.2012
Matthias Hlawatsch 13,2k 4 9
Nein, ich habe den Code 1:1 aus dem Editor kopiert.
Fahren ist auch nicth statisch. Eine ganz normale Methode.
Maik_1978 05.11.2012
Hmmm... Siehe mein Update.
Matthias Hlawatsch 05.11.2012
Es ist vollkommen egal ob ich das delete oder die NULL-Zuweisung entferne. In beiden Fällen wird Fahren() ausgeführt.
Ich würde es nicht glauben wenn ich es nicht direkt vor mir sehen würde!!!
Maik_1978 05.11.2012
2
Siehe Update 2. Was bin ich froh, dass ich mit dieser Sprache normalerweise nichts zu tun habe!
Matthias Hlawatsch 05.11.2012
Danke für Deine Mühe Matthias, das ist wirklich krass.
Maik_1978 05.11.2012

Stelle deine Cplusplus-Frage jetzt!