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;