Thema: Delphi "Unsterbliche" Klassen

Einzelnen Beitrag anzeigen

Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.840 Beiträge
 
Delphi 10 Seattle Enterprise
 
#47

Re: "Unsterbliche" Klassen

  Alt 15. Dez 2005, 17:10
Zitat von Dax:
Delphi-Quellcode:
var Unv : TUnverwundbar;
Unv.CleanupInstance;
FreeMem(Pointer(Unv), TUnverwundbar.InstanceSize);
Sollte aber eventuell gehen.. Oder?
Mach es doch so, das funktioniert auf jeden Fall. (getestet)

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var x : TUnverwundbar;
begin
  x := TUnverwundbar.Create;
  x.TestString := 'Test';

  x.CleanupInstance; // Aufräumen
  SysFreeMem(Pointer(x)); // und aus Speicher entfernen

  Caption := x.TestString;
end;
Ein paar Worte dazu:
Wenn ein (obj as TObject).Free aufgerufen wird,
wird Destroy, _ClassDestroy, FreeInstance aufgerufen.
in FreeInstance wird dann CleanupInstance und
MemoryManager.FreeMem (der auf SysFreeMem zeigt) aufgerufen.

Obiges Beispiel macht also genau das selbe wie x.Free sollte

Hier noch mal ein Auszug aus der System.pas zum Nachlesen und verstehen:
(Anmerkung: in der system.pas sind manche Proueduren und Funktionen mit dem beginnenden Unterstrich (z.B. _ClassDestroy). Diese Funktionen benutzen die "CompilerMagic". Das bedeutet, das teile der Funktionalität fest im Compiler eingebaut sind. Nach dem "Destroy" eines Objektes wird immer _ClassDestroy aufgerufen, obwohl das in der System.pas gar nicht programmiert ist. Das baut der Compiler von sich aus ein It's magic, compiler magic.)
Delphi-Quellcode:
{*******************************************************}
{       Borland Delphi Runtime Library                  }
{       System Unit                                     }
{       Copyright (C) 1988,99 Inprise Corporation       }
{*******************************************************}
unit System; { Predefined constants, types, procedures, }
...
interface
...
type
...
  TObject = class
    ...
    procedure Free;
    procedure CleanupInstance;
    ...
    procedure FreeInstance; virtual;
    destructor Destroy; virtual;
  end;
...
  PMemoryManager = ^TMemoryManager;
  TMemoryManager = record
    GetMem: function(Size: Integer): Pointer;
    FreeMem: function(P: Pointer): Integer;
    ReallocMem: function(P: Pointer; Size: Integer): Pointer;
  end;
...
{ Procedures and functions that need compiler magic }
procedure _ClassDestroy(Instance: TObject);
function _FreeMem(P: Pointer): Integer;
...
implementation
...
procedure TObject.Free;
begin
  if Self <> nil then
    Destroy; // Free ruft Destroy auf
end;
...
destructor TObject.Destroy;
begin
  // Destroy ist leer :shock:
  // Es wird aber dann automatisch _ClassDestroy(self) aufgerufen
end;
..
procedure _ClassDestroy(Instance: TObject);
begin
  Instance.FreeInstance; // aha, hier also ;-) !!!
end;
...
procedure TObject.FreeInstance;
begin
  CleanupInstance; // Räumt auf
  _FreeMem(Self); // Entfernt Objekt aus dem Speicher
end;
...
procedure TObject.CleanupInstance;
var
  ClassPtr: TClass;
  InitTable: Pointer;
begin
  ClassPtr := ClassType;
  InitTable := PPointer(Integer(ClassPtr) + vmtInitTable)^;
  while (ClassPtr <> nil) and (InitTable <> nil) do
  begin
    _FinalizeRecord(Self, InitTable);
    ClassPtr := ClassPtr.ClassParent;
    if ClassPtr <> nil then
      InitTable := PPointer(Integer(ClassPtr) + vmtInitTable)^;
  end;
end;
...
function _FreeMem(P: Pointer): Integer;
begin
  if P <> nil then
  begin
    Result := MemoryManager.FreeMem(P); // Aha, also der Memorymanager !!!
    if Result <> 0 then
      Error(reInvalidPtr);
  end
  else
    Result := 0;
end;
...
var
  MemoryManager: TMemoryManager = (
    GetMem: SysGetMem;
    FreeMem: SysFreeMem; // Der MemoryManager benutzt per Default SysFreeMem
    ReallocMem: SysReallocMem);
...
function SysFreeMem(P: Pointer): Integer;
begin
  __free(P); // ist extern definiert
  Result := 0;
end;
...
end;
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat