@Choose:
hier ist mein Code aus dem
DEC ->
Unit DECutil.pas
Delphi-Quellcode:
function IsClass(AObject: Pointer; AClass: TClass): Boolean;
assembler;
register;
asm // safer replacement for Borland's "is" operator
@@1: TEST EAX,EAX
JE @@3
MOV EAX,[EAX]
TEST EAX,EAX
JE @@3
CMP EAX,EDX
JE @@2
MOV EAX,[EAX].vmtParent
JMP @@1
@@2: MOV EAX,1
@@3:
end;
function IsObject(AObject: Pointer; AClass: TClass): Boolean;
// Relacement of "is" Operator for safer access/check iff AObject is AClass
begin
Result := False;
if AObject <>
nil then
try
Result := IsClass(AObject, AClass);
except
end;
end;
Zitat:
man könnte einen Speicherbereich prüfen ob es ein Objekt repräsentiert
Man kann es zwar prüfen aber das bringt eben nichts.
Ein Object A wird an Addresse $1234567 erzeugt und wieder freigeben. Nun wird Object B mit gleichem Speicherverbrauch erzeugt. Der Speichermanager alloziert den Speicher auf grundf seiner internen Logik wiederum an Addresse $12345678. Somit würde ein Zugriff über eine Variable die ehemals ein Object A enthielte nun auf Object B zugreifen. Object A und B müssen aber nicht vom geleichen Typ sein oder könnten ganz andere Daten enthalten.
Mit Multithreading o.ä. hat das erstmal überhaupt nichts zu tun, es geht einfach um die Aussage das es KEINE sauberen Weg gibt eine Variable die ein Object enthält das freigeben wurde zu überprüfen ob das Object noch gültig ist.
Nur zwei Lösung gibt es für das Problem:
1.) sicherstellen das das freizugebene Object alle auf sich bezogenen Variablen auf NIL setzt. TComponent.FreeNotification() benutzt so eine Technik indem jedes TComponent eine TList von verlinkten Komponenten verwaltet. Speichert eine solche verlinkte Komponente eine Referenz auf Component A so kann es mit .FreeNotification() sich selbst registrieren. Beim Freigeben der Komponente ruft diese die Methode .Notification() für jeder der mit .FreeNotofiocation() registrierten Komponenten auf. Diese Technik könnte man auch für einfache Variablen benutzen. Allerdings hat diese Technik einen Hacken. Man muß nämlich jeweils BEIDE Komponenten gegenseitig registrieren. D.h. A -> B und B -> A, damit es eben nicht passieren kann das bei freigeben von A ein ungültiges B benachrichtigt wird.
2.) Einfach sicherstellen das solange irgendeine gültige Referenz existiert auch das Object nicht freigegeben wird. So arbeiten Interfaces. Ich halte diesen Weg für den saubersten da er vom Denkmodell Top-Down orientiert ist.
Im dezeitigen Zustand des MM's und des Compiliers kann es keine Lösung geben. Man müsste schon den kompletten Compiler und MM umschreiben. In einem solchen Szenario wäre es vorstellbar das der Compiler über Magic einen virtuellen Pointer in eine Pointer Tabelle mappt. Diese Tabelle wäre Bestandteil des Speichermanagers und mappt die virtuellen Pointer zur korrekten Speicheradresse. D.h. jedesmal wenn der Compiler ein Object derefernzieren will muß der Compiler diese Magic benutzen. Nun ist es möglich die Zeigertabelle zum mappen so aufzubauen das ein sequentieller Gültigkeitszähler integriert wird.
Gruß Hagen