AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

IsObject / IsClass

Ein Thema von choose · begonnen am 3. Feb 2004 · letzter Beitrag vom 22. Nov 2005
Antwort Antwort
Seite 1 von 3  1 23      
choose

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

IsObject / IsClass

  Alt 3. Feb 2004, 13:29
Oft wird Delphi-Neulingen geraten, bei der Arbeit mit Objekten die Referenzen nach der Freigabe eines Objekts (zB mit FreeAndNil) wieder auf nil zu setzen, damit ein Vergleich der Form
if Assigned(AnObject) then eingesetzt werden kann, um zu überprüfen, ob es sich um eine gültige Referenz handelt.
Der Compiler von Delphi initialisiert Objektreferenzen innerhalb von Methoden und Prozeduren/Funktionen nicht vor, so dass ein Test der Art
Delphi-Quellcode:
procedure MyProc;
var
  myObject: TObject;
begin
  if Assigned(myObject) then
zwar überprüft, ob die Referenz (hier: myObject) einen Wert hält, der von nil verschieden ist, kann aber im Fall einer "durch Zufall" von nil verschiedenen "Vorbelegung" nicht entscheiden, ob der Wert nun tatsächlich auf ein Objekt verweist.

Innerhalb des DEC und der JCL konnte ich nun zwei verschiedene Implementierungen einer Funktion IsObject (bei der JCL auch eine IsClass für Klassenreferenzen) finden, die zwei unterschiedliche Ansätze verfolgen.
Die Lösung von Hagen prüft, sofern ich sie nicht missdeute, ob vor dem Speicher, in dem das vermeintliche Objekt liegt, einen MagicCode enthält (genauer ein Bit), der vom Borland-Speichermanager dort hinterlegt worden sein sollte.
Die Lösung innerhalb der JCL geht davon aus, dass ein Objekt zu einer Klasse gehört und überprüft innerhalb der VMT der Klasse, ob die dort erwartete Referenz auf die Klasse selbst vorhanden ist.

Während Hagens Ansatz schneller arbeiten sollte kann bei zufälligen Werten (durch eine zufällig vorbelegte lokale Referenz) durch seine Maskierung der Form if MagicCode and $2 = $2 then nur zu 50% gesagt werden, ob es sich um ein Objekt handelt. Aus informationstheoretischer Sicht ist dies keine Information, also nutzlos für diesen Fall, obgleich die Routine für andere Szenarien korrekt arbeiten sollte. Darüber hinaus könnte dieser Ansatz nicht mehr funktionieren, wenn man die Speichervergabe von Objekten über eine eigene Implementierung (NodeManager) lösen würde, die ohne den MagicCode auskommt.
Der Ansatz der JCL prüft zwar ein wesentlich unwahrscheinlicheres Kriterium, hat aber gegenüber der Lösung aus dem DEC den Nachteil, das er mit diversen Indirektionen arbeitet, also im Speicher liest, obgleich es bei der Interpretation von nicht-initialisierten Referenzen sein kann, dass keine Leserechte zu den entsprechenden Speicherbereichen existieren. Hagens Lösung hingegen "schluckt" solche Fehler (durch einen try-except-Block) und gibt für diesen Fall den erwarteten Wert False zurück.

In der Vergangenheit habe ich eine zur JCL ähnliche Lösung entwickelt, die mithilfe der funktion IsBadReadPtr überprüft, ob die Bereiche gelesen werden können und außerdem beim Sonderfall nil abkürzt, so dass sie als Alternative für Assigned eingesetzt werden könnte.
Leider ist diese Implementierung etwas langsamer als der Ansatz der JCL und bei weitem inperformanter als die Lösung aus dem DEC.
Darüber hinaus vermag auch dieser Ansatz (genauso wie die beiden anderen) nicht das volgende Szenarium korrekt zu erfassen
Delphi-Quellcode:
var
  myObject: TObject;
begin
  myObject:= TObject.Create;
  myObject.Free;
  if IsObject(myObject) then
weil der Speicher hinter dem durch den Destructor freigegeben Objekt nicht gelöscht wird und somit weiterhin auf eine gültige Klasse verweist. Auch der MagicCode des Borland-Speichermanagers zeigt weiterhin das geforderte Kriterium, so dass ich bisher keine geeignete Lösung des Problems zur identifizierung einer gültigen Objektreferenz ausmachen konnte.

Hat jemand eine Lösung?
gruß, choose
  Mit Zitat antworten Zitat
Touchdown

Registriert seit: 17. Feb 2003
227 Beiträge
 
#2

Re: IsObject / IsClass

  Alt 3. Feb 2004, 13:50
Das wird nicht leicht, in deinem unteren Beispiel ändert sich tatsächlich für den Pointer ja nichts, er zeigt immer noch auf den gleichen Speicherbereich. Der Haken an der Sache, dieser Speicher ist für die Anwendung nicht mehr freigegeben.

Genau da würde ich nach einer Lösung suchen, aber einfach ist es sicher nicht. Da muss man wohl mit Speicherverwaltung des OS rumschlagen
function getallfornothing: TGoldesel;
begin
result := TGoldesel.create;
end;
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#3

Re: IsObject / IsClass

  Alt 3. Feb 2004, 21:01
Ich weiß nicht welchen Code du von IsObject() von mir analysiert hast. Meine isObject() Funktion fragt nicht ab ob der Speicherzeiger ein Magic enthält. Dies darf er auch garnicht, da es ja nicht gesagt ist das der Borland MM benutzt wird. IsObject() überprüft so wie die Borland Funktion "is" ob es sich um ein gültiges Object abgeleitet von TObject handelt. Dabei lädt sie die VMT der Objectinstance und überprüft ab da rekursiv die Klassentypen bis hinab zu TObject. Somit ist IsObject fast identisch wie IsClass(). Allerdings, habe ich eine andere Assembler Routinie als Ersatz für "is" benutzt, die eben SICHER gegen nil Pointer in den VMT's ist. Dies ist beim Borland Original "is" Operator NICHT der Fall. Zusätzlich zu dem habe ich noch einen try except Block eingebaut um eventuelle AV's abzufangen.

Aber grundsätzlich gibts für deine Problem keine saubere Lösung, das stimmt.
Man kann noch eine Verbesserung durchführen indem man TObject.FreeInstance() überschreibt oder eben hookt/patcht. Die neue .FreeInstance Klassenmethode gibt so wie die originale den Speicher frei, überschreibt aber vorher mit FillChar(Self^, Self.InstanceSize) den Speicher des Objectes mit Nullen. Da Self^^ ein Zeiger auf die Klasse des Objectes ist, heist dies das nun der IS Operator auf einen NIL Zeiger zur VMT des Objectes zugreift. In diesem Moment wird also nochmal ca. 50% die Wahrscheinlichkeit erhöht falsche Objecte zu finden.

Allerdings, dies hilft dir nur im Beispiel deines obigen Codes. Nach dem Object.Free ist nämlich Object^ = Object.PointerToClass == NIL. Würdest du aber sofort nach dem .Free wiederum ein Object erzeugen, mit gleicher Größe wie das vorherige, so benutzt der Speichermanager exakt den Speicher des vorher freigegeben Objectes erneut. Somit befindet sich an der Speicheradresse von Object nun wieder ein gültiges Object, es IST aber NICHT das gleiche Object !!

also:

Delphi-Quellcode:
var
  A,B: TMyObject;
begin
  A := TMyObject.Create(1);
  A.Free;
  if not IsObject(A) then
    "Alles Ok !"

  B := TMyObject.Create(2);
  if A = B then
    "sehr wahrscheinlicher Fall das A = B ist da MM Speicher wiederverwendet"

  if IsObject(A) then
    "Integer(A) = Integer(B), aber NICHT das gleiche Object"
end;
Gruß Hagen
  Mit Zitat antworten Zitat
choose

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

Re: IsObject / IsClass

  Alt 4. Feb 2004, 08:26
Hallo Hagen,
Zitat von negaH:
Ich weiß nicht welchen Code du von IsObject() von mir analysiert hast.
ich berufe mich auf die Unit DEC_api vom 26.08.1999 (zugegeben, etwas alt?), in der folgende Abfrage zufinden ist:
if (PInteger(PChar(AObject) - SizeOf(Integer))^ and $00000002 = $00000002) bevor der Vergleich auf die Klasse stattfindet.

Zitat von negaH:
Dabei lädt sie die VMT der Objectinstance und überprüft ab da rekursiv die Klassentypen bis hinab zu TObject.
Diese Implemenentierung konnte ich weder in der DEC_api noch in der DECUtil vom 26.08.1999 mit if TObject(AObject) is AClass entdecken.
Die von Dir beschriebene Variante mit der zusätzlichen Prüfung auf nil erfüllt mit der Möglichkeit auf die Prüfung einer konkreten Schnittstelle (Typen) noch eine zusätzliche Funktion, jedoch arbeitet sie bei zufällig (von nil verschiedenen) Werten auf zusammenhangslosen Daten fehlerhaft, so dass Du willkürliche Informationen gegen eine übergebene Klassenreferenz testest darüber hinaus nicht ausschließen kannst, in Endlosschleifen "hängenzubleiben", sofern ich das richtig verstanden habe.

Zitat von negaH:
Man kann noch eine Verbesserung durchführen indem man TObject.FreeInstance() überschreibt oder eben hookt/patcht.
An diesen Ansatz hatte ich auch schon gedacht und entspricht wohl dem, was Touchdown meinte(?). Zumindest für den Fall der gerade freigegebenen Objekte könnte so in einer SingleThread-Anwendung oder bei einer Implementierung des MM, bei der jeder Thread unterschiedliche Bereiche von Speicher zugewiesen bekommt, gelöst werden.
Das Problem sah ich bei dieser Lösung, genau wie Du, bei der erneuten Vergabe (zB durch weiteren Thread), die auch nicht unmittelbar später erfolgen muss, sondern bei Strukturen homogener Klassen auch nach mehrfacher Freigabe und Neuvergabe von Speicher auftreten kann.

Es ist die Frage, ob dies nicht vielleicht sogar gewollt ist, wenn die Routine IsObject lediglich prüfen soll, ob hinter einer Referenz tatsächlich ein Objekt steht. Es liegt in der Natur der Referenzen, dass sie nicht surjektiv sind, so dass der von Dir beschriebene Fall nicht von einer Zuweisung der Form
myRef:= anotherRef; unterschieden werden kann (und sollte?).


Es bleibt folglich das Problem der fälschlichen Verarbeitung von zuälligen Daten (auch mit der von mir vorgeschlagenen Prüfung auf die Selbstreferenz einer Klasse nach einer Prüfung auf die Lesbarkeit des Speichers ist dies nur zu einer endlichen Wahrscheinlichkeit möglich) und der zusätzliche Zeitaufwand bei der Freigabe von Objekten (abgesehen davon, dass nicht gerantiert ist, dass die Implementierung von TObject.FreeInstance aufgerufen wird (NodeManager)).

Weiß jemand weiter?
gruß, choose
  Mit Zitat antworten Zitat
Touchdown

Registriert seit: 17. Feb 2003
227 Beiträge
 
#5

Re: IsObject / IsClass

  Alt 4. Feb 2004, 10:24
Ich glaube euer Ansatz ist teilweise falsch, man könnte einen Speicherbereich prüfen ob es ein Objekt repräsentiert, das Ergebnis ist jedoch vollkommen uninteressant, wenn dieser Speicherbereich nicht für die Anwendung freigegeben ist. Bin nun wirklich kein Experte bzgl. Thread-Programmierung, denke aber, dass alle Threads einer Anwendung den gesamten Speicherbereich der Anwendung nutzen können. Falls dem nicht so ist, wird es noch ein wenig komplizierter.
function getallfornothing: TGoldesel;
begin
result := TGoldesel.create;
end;
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#6

Re: IsObject / IsClass

  Alt 4. Feb 2004, 14:51
@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
  Mit Zitat antworten Zitat
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
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#8

Re: IsObject / IsClass

  Alt 4. Feb 2004, 18:43
Hi Choose,

deine Überprüfung auf zirkuläre Referenzen ist ebenfalls nicht 100%'tig sicher. Angenommen die Klasse ist die 10'te Klasse in einer Hirarchie. Dann würde deine Absicherung im Source nur mit 1/(10*10)'tel besser sein als garkeine Überprüfung auf zirkuläre Referenzen. Denn es kann an jeder Stelle der VTM.Parent Hierarchie die zirkulare Referenz zu jeder der anderen Klassen in der Hirarchie auftreten.
Somit müsste deine IsClass() Überprüfung auf zirkuläre Referenzen viel weiter ausgebaut werden.

Es gibt noch drei zusätzliche Möglichkeiten IsClass() mehr abzusichern:
1.) in der RTTI/VMT ist selber ein Feld das als vmtSelfPtr bezeichnet wird. Eine gültige Klasse muß in diesem Feld auf sich selber zeigen.
2.) eine gültige Klasse sollte immer im Codesegment gespeichert werden. Bis auf einem Ausnahme, meine eigene Testimplementierung, kenne ich keinen Delphi Source der dynamisch Klassen zur Laufzeit konstruiert. D.h. man kann mit 99.99% Wahrscheinlichkeit sagen das der Zeiger auf die Klasse im Codesegement liegen muß.
3.) man kann über alle Typ Information der Anwendung und seiner geladenen Module iterieren. Die Klassen Strukturen sind nur ein Teil dieser Typinformation die der Compiler hardcoded erzeugt. Man kann nun diese Iteration über die Typinfo's als Referenzquelle für gültige Zeiger von allen im Projekt verwendeten Klassen benutzen. Damit ließe sich auch das Problem eventueller zirkulärer Referenzen beseitigen. Man iteriert über die Typinformation bis man die Klasse zum Object gefunden hat. Nun geht man iterativ die Klassenhierarchie top-down.

Da fällt mir ein, zirkuläre Referenzen IN der Klassenhierarchie können nur auftreten wenn man das Codesegment modifiziert, also patcht. Sie sind also enorm unwahrscheinlich und würden NICHT eine Object-Instance ansich betreffen sondern die komplette Klasse. D.h. ALLE Objectinstancen der gleichen Klasse würden den selben Fehler in ihrer Klassenhierarchie enthalten. Ziemlich unwahscheinlich also da der Compilier die Klassenhierarchien hardcoded im Codesegment eincompiliert. Auf Grund der Delphi Sprachdefinitionen ist es aber nicht möglich zirkuläre Klassenhierarchien zu konstruieren. Es müsste also schon im Codesegment hineingepatcht wurden sein.

Gruß Hagen
  Mit Zitat antworten Zitat
choose

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

Re: IsObject / IsClass

  Alt 4. Feb 2004, 22:09
Hallo Hagen,
Zitat von negaH:
deine Überprüfung auf zirkuläre Referenzen ist ebenfalls nicht 100%'tig sicher.
Ich bin mir nicht ganz sicher, welche Lösung Du hier ansprichst. Weder mein Code prüft soetwas ab noch sprach ich zirkuläre Hierarchien in der Vererbung an. Mein Beispiel aus der Funktion TakeIsClassForARide sollte lediglich unglückliche willkürliche Daten Repräsentieren. Den Fall, bei dem die eingangs gewählte zu überprüfende Referenz zufällig auf willkürliche Daten verweist (zB als "Rückstände" auf dem Stack). Einer der schlechtesten solche Fälle wären hierbei Daten sie -rein zufällig- so beschaffen sein könnten, dass Dein Code sie als zyklisch interpretiert und in einer Endlosschleife zu keinem Ergebnis kommt.
Auch mein Vorschlag könnte zufällige Daten missinterpretieren (also True zurückgeben obgleich hinter einem Datenbereich kein Objekt existiert), aber auch im worst-case nicht zu einer Endlosschleife führen.
Hast Du zu solchen Daten eine bessere Idee?

Darüber hinaus sprach ich zirkuläre Referenzen im Zusammenhang mit Interfaces an, konkret: die von Delphi implementierten Referenzzählung. Auch hier ging es weder um die Vererbungshierarchie (auf die bei Interfaces wohl auch eher selten geprüft wird, obgleich dies möglich ist) noch auf eventuelle Zyklen in ihr sondern um das Problem von "verhakten Clustern" von Objekten, die gegenseitig ihre Referenzen halten und in anderen Umegbungen nur mit einem Garbage Collector aufgelöst werden konnten.


Zitat von negaH:
1.) in der RTTI/VMT ist selber ein Feld das als vmtSelfPtr bezeichnet wird. Eine gültige Klasse muß in diesem Feld auf sich selber zeigen.
Und eben genau diesen Ansatz verfolgt mein obiger Code.

Zitat von negaH:
2.) eine gültige Klasse sollte immer im Codesegment gespeichert werden. Bis auf einem Ausnahme, meine eigene Testimplementierung, kenne ich keinen Delphi Source der dynamisch Klassen zur Laufzeit konstruiert.
Ich habe zwar an Lösungen dieser Art gearbeitet, konnte letztlich aber doch jedes Problem mit OOP-Patterns oder Code-Generation lösen. Ich glaube deshalb ebenfalls, dass diese Fall vernachlässigt werden kann.

Zitat von negaH:
3.) man kann über alle Typ Information der Anwendung und seiner geladenen Module iterieren.
Dieser Ansatz klingt sehr interessant: Es könnte mit TObject.ClassType geprüft werden, ob eine gültige Klassenreferenz in der RTTI abgelegt worden ist. Siehst Du hier in Kombination mit der Selbstreferenz noch ein Problem? Die Warhscheinlichkeit, dass bei zufälligem Speicher die Selbst-Referenz identisch ist (bei absolut zufälligen Daten) mit der Klasse selbst, liegt bei 1/2^32. Multipliziert mit der Wahrscheinlichkeit n/2^32, dass es sich bei der Wert um eine der n gültigen Klassen handelt, ergibt sich nach diesem Ansatz eine Wahrscheinlichkeit von n/2^64. Geht man von weiterhin weniger als 16000 Klassen aus, liegt die Wahrscheinlichkeit einer Fehlinterpretation zufälliger Daten folglich bei weniger als 1/2^50.
Die anderen Fälle sollten bei den bisherigen Betrachtungen als ausgeschlossen gelten.


Für diesen Ansatz müsste jedoch sichergestellt werden, dass die TypeInfo/TypeData jeder Klasse zugänglich ist. Bisher habe ich Registraturen (zB für ein dynamisches Factory-Pattern) ähnlich der Funktion RegisterClass händisch implementiert. Kannst Du einmal zeigen, wie man über alle RTTI aller Datentypen iterieren kann?
gruß, choose
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#10

Re: IsObject / IsClass

  Alt 5. Feb 2004, 18:22
Hi Choose,

ich hatte hier im Forum schon mal einen solchen Code gepostet. Dieser Source konnte über alle deklarierten TypInfos der geladenenen Module iterieren. D.h. alle TypInfos die auch mit der Funktion TypInfo(XYZ) abgefragt werden können konnten mit der Funktion EnumTypeInfo() durchiteriert werden.

Nun, ich habe danch im Forum gesucht und konnte es nicht mehr finden, vielleicht findest du es ja.

Gruß Hagen
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:04 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz