Thema: Delphi IsObject / IsClass

Einzelnen Beitrag anzeigen

choose

Registriert seit: 2. Nov 2003
Ort: Bei Kiel, SH
729 Beiträge
 
Delphi 2006 Architect
 
#7

Re: IsObject / IsClass

  Alt 4. Feb 2004, 15:25
Hallo Hagen,

zunächst einmal möchte ich die Problematik mit der Endlosschleife (zugegen, recht unwahrscheinlich) bei Deiner Implementierung auf ungüültigen Daten genauer demonstrieren:
Delphi-Quellcode:
procedure TakeIsClassForARide;
var
  myCircularData : record
    vmtParent : Pointer; // -36
    vmtSafeCallException : Integer; // -32
    vmtAfterConstruction : Integer; // -28
    vmtBeforeDestruction : Integer; // -24
    vmtDispatch : Integer; // -20
    vmtDefaultHandler : Integer; // -16
    vmtNewInstance : Integer; // -12
    vmtFreeInstance : Integer; // -8
    vmtDestroy : Integer; // -4
    ClassOffsetZero : Pointer;
  end;
begin
  myCircularData.vmtParent:= @myCircularData.ClassOffsetZero;
  myCircularData.ClassOffsetZero:= @myCircularData.ClassOffsetZero;
  IsClass(@myCircularData, TObject);
end;
um Dir weiterhin beizupflichten: Es können auch Objekte anderer Klassen an derselben Adresse abgelegt werden. Weil die Identität eines Objekts nach dem Ansatz in Delphi aber genau durch diesen Ort definiert ist und Referenzen weiterhin nicht eineindeitig (sondern nur injektiv) einem Objekt zugeordnet sind, ist es fraglich, ob die Funktion IsObject nicht vielleicht per definition korrekt arbeitet, wenn sie für diesen Fall erneut True zurückgibt.
Die Idee mit den Threads wollte ich nur anführen, um zu zeigen dass auch bei Konstrukten der Art
Delphi-Quellcode:
var
  myRef: TObject;
begin
  myRef:= TObject.Create;
  myRef.Free;
  // thread may create another object o right now
  IsObject(myObject) // <- result is undefined (myObject may be object o)
Zitat von negaH:
1.) sicherstellen das das freizugebene Object alle auf sich bezogenen Variablen auf NIL setzt.
Denkbar, aber nur mit einer Registrierung aller Referenzen. Es bleibt dabei fraglich, wie vorgegeben werden sollte, wenn Referenzen threadübergreifen genutzt werden: Wird ein Objekt innerhalb des einen Ausführungsstrangs freigegeben, müsste die Referenz des anderen Threads genilt werden. Ein Programmcode kann deshalb nicht länger von korrekten Werten innerhalb (lokaler) Variablen ausgehen, da sie "von außen" jeder Zeit verändert werden könnten, bzw es müssten viele Bereiche definiert werden, in denen ein solcher "Entzug" nicht zulässig ist. Dann sind Deadlocks vorprogrammiert.

Zitat von negaH:
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.
Nicht immer sind Daten Top-Down organisiert, so dass es bei einem schlichten Ansatz, wie dem der Delphi-Referenzzählung, bei komplexeren zyklischen Strukturen zu Problemen kommt.

Zitat von negaH:
Im dezeitigen Zustand des MM's und des Compiliers kann es keine Lösung geben.
Das denke ich leider auch.


Anbei der Code, den ich verwende
Delphi-Quellcode:
function IsClass(const AClass: TClass): Boolean; assembler;
asm
  // EAX = AClass
  OR EAX, EAX // AClass = nil
  JE @OUT
  MOV EBX, EAX // store class reference

  PUSH 4 // valid pointer -> class self reference readable
  ADD EAX, vmtSelfPtr
  PUSH EAX
  CALL IsBadReadPtr
  OR EAX, EAX
  JNE @FALSE

  MOV EAX, EBX
  SUB EAX, EAX.vmtSelfPtr // test class against self reference
  JNE @FALSE
  INC EAX // Result:= True
  RET

  @FALSE:
  XOR EAX, EAX // Result:= False
  @OUT:
end;

function IsObject(const AnObject: TObject): Boolean; assembler;
asm
  // EAX = AnObject
  OR EAX, EAX // AnObject = nil
  JE @OUT

  MOV EBX, EAX // store object reference

  PUSH 4 // valid Pointer -> class readable
  PUSH EAX
  CALL IsBadReadPtr
  OR EAX, EAX
  JNE @FALSE

  MOV EAX, [EBX] // class reference
  JMP IsClass // Result:= IsClass(EAX)
  @FALSE:
  XOR EAX, EAX // result:= False
  @OUT:
end;
Es bleibt nach meiner Ansicht die Frage nach einer eine möglichst sicheren Prüfung auf zufälligen Daten.
gruß, choose
  Mit Zitat antworten Zitat