Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - inherited Free Problem


knittel - Fr 08.03.13 23:28
Titel: inherited Free Problem
Hallo allerseits,

Ich hab bei meinem Objekt ein Prozedur eingebaut, die alle inneren Objekt teile entfernt und ich habe diese Destruction() genannt:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure TMeStatic.Destruction();
begin
glDeleteLists(FDisplayList, 1);
FVertices.Free();
FNormals.Free();
FColors.Free();
FTextureCoords.Free();
FFaces.Free();
end;


Der Destruktor dieses Objekts sieht folgendermaßen aus:


Delphi-Quelltext
1:
2:
3:
4:
5:
destructor TMeStatic.Free();
begin
Destruction();
inherited Free;
end;


So wenn ich dann den destructor aufrufe erhalte ich eine Access Violation.

Wenn ich aber den eigenen Destruktor entferne und das ganze so aufrufe:


Delphi-Quelltext
1:
2:
MyStatic.Destruction();
MyStatic.Free();


dann erhalte ich keine Fehlermeldung. :gruebel:

Kann mir irgendjemand sagen was ich falsch mache? Danke schonmal. ;)


bummi - Sa 09.03.13 00:44

Der Destructor ist immer Destroy.
Du kannst entweder Deinen Destructor so implementieren

Delphi-Quelltext
1:
2:
3:
  TMyClass=Class(Tobject)
    Destructor Destroy;override;
  End;


oder wenn Du unbedingt Free verdecken willst


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
  TMyClass=Class(Tobject)
    Destructor Free; 
  End;

// dann zumindest den Destructor aufrufen

Destructor TMyClass.Free; 
begin
  // irgendwas an Code
  inherited Destroy;
end;



Ich habe noch ein Beispiel dessen angehängt was bei Deiner Aufrufvariante passiert:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
unit Unit2;

interface

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

type
  TMyClass=Class
  public
    Procedure Demo;
    Destructor Free;
  End;
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
begin
     ReportMemoryLeaksOnShutDown := true;
     With TMyClass.Create do Free;
end;

{ TMyClass }
// entspricht Free
procedure TMyClass.Demo;
begin
  // hier ist self nicht nil aber schon ungültig da der Destruktur das Objekt verworfen hat
  if self <> nil then Destroy;
end;


Destructor TMyClass.Free;
begin
  Showmessage('Hallo2')  ;
  Demo; // entspricht Deinem Aufruf von inherited free;
end;

end.


knittel - Sa 09.03.13 01:28

OK. Ich verwende absofort "inherited Destroy", Vielen Dank! :)

P.S. Hab sonst in Tutorials usw. immer Free gesehen und mich daher auch daran gewöhnt.


Martok - Sa 09.03.13 02:55

Du solltest immer Free aufrufen, aber nur Destroy überschreiben.

Free macht noch ein paar (wichtige) Überprüfungen, bevor es für die eigentliche Arbeit Destroy aufruft. Und es ist nicht virtual, du kannst es also gar nicht so überschreiben wie du dir das denkst.

Und einen destructor Free zu nennen ist auf so viele Arten falsch und verwirrend und gradezu bösartig den Konventionen widersprechend, da will ich gar nichts mehr zu sagen :zwinker: