2017-06-25 3 views
3

Der folgende Code funktioniert gut, aber es sollte nicht! Wenn ich auf den Button1 klicke, wird das Objekt zuerst zerstört, und dann wird sein Wert verwendet und ich erhalte keine Zugriffsverletzung oder etwas ... Mehr noch, die Multiplikationsoperation gibt das korrekte Ergebnis, das beweist, dass Obj1 nicht zerstört wird ! Aber auch das ist nicht wahr, denn wenn ich das Programm schließe, meldet es keinen Speicherverlust. Ich bin sehr verwirrt.Warum erhalte ich keine Ausnahme, wenn ich das Objekt benutze, nachdem ich es zerstört habe?

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, StdCtrls; 

type 
    MyObj = class(TObject) 
    Value: Cardinal; 
    end; 

    TForm1 = class(TForm) 
    Button1: TButton; 
    procedure FormCreate(Sender: TObject); 
    procedure Button1Click(Sender: TObject); 
    public 
    Obj1:MyObj; 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
Obj1.Free; 
Obj1.Value:=Obj1.Value * 5; 
Caption:=IntToStr(Obj1.Value); 
end; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
ReportMemoryLeaksOnShutdown:=true; 
Obj1:=MyObj.Create; 
Obj1.Value:=10; 
end; 

end. 
+0

Es ist, weil der Speicher noch gültig ist; Sie schreiben gerade an Speicherorte. Sie könnten zu diesem Zeitpunkt über andere Objekte kritzeln. –

Antwort

5

Das Objekt ist zerstört. Der Speicher wird an den Speichermanager zurückgegeben. Was als nächstes passiert, liegt außerhalb Ihrer Kontrolle. Der Speicher könnte an das System zurückgegeben werden. In diesem Fall würden Sie einen Laufzeitfehler sehen. Oder der Speicher könnte durch den Speichermanager am Leben gehalten werden, bereit, das nächste Mal, wenn das Programm nach einem Block dieser Größe fragt, wiederzuverwenden. Das passiert hier.

Ihr Programm weist ein undefiniertes Verhalten auf. Alles könnte passieren, auch das Programm scheint zu funktionieren. Offensichtlich ist das Programm falsch und Sie dürfen nicht auf Objekte zugreifen, nachdem diese zerstört wurden.

Wenn Sie die vollständige Debug-Version von FastMM verwenden, sollte ein Fehler angezeigt werden, da in diesem Szenario Schritte unternommen werden, um den freien Zugriff zu erkennen. Das ist ein nützliches Debugging-Tool.

+0

doesnt Zuweisung von NIL zu einem freigegebenen Objekt würde hier helfen? – GuidoG

+0

@GuidoG Das Zuweisen von NIL zu genau dieser Referenz hilft nicht unbedingt, da es andere Referenzen geben könnte. –

+0

@ GünthertheBeautiful ja ich kenne die dangling Pointersituation, aber im Beispielcode des OP würde er Obj1 machen: = NIL; nach dem freien würde das wieder eine ausnahme auslösen, oder? – GuidoG

Verwandte Themen