Thema: Delphi RTTI-Bugs?

Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#1

RTTI-Bugs?

  Alt 5. Mai 2014, 09:07
Delphi-Version: XE5
Moin,

kennt jemand weitere Fehler in der RTTI?
  • falsche Daten bei Sets über 8 Byte (mehr als 64 Elemente)
    Das resultiert dann in falschen TypeSize in der RTTI
  • bei Array-Property (TRttiIndexedProperty) fehlt der Indexbezeichner, bzw. der wird direkt zum Index des Arrays gezählt, wobei aber der Wert dieser Angabe verloren geht.
    Das "wobei" erkennt man auch an dem Eintrag zum "Indexbezeichner" in der OH.
  • einige ToString-Methoden der RTTI, womit man die Deklaration (teilweise) abfragen kann, lösen gern Zugriffsverletzungen aus, wenn sie mit einem seltenern Sonderfall des Aufbaus zusammenstoßen, oder wenn nicht alle nötigen RTTI-Infos einkompiliert wurden.
    (nja, muß man das halt selber in Text übersetzen, was allerdings nicht immer so einfach ist, da nötige Basisfunktionen nicht öffentlich zugänglich sind ... zum Glück kann man da notfalls via RTTI ran, oder man kopiert die Funktionen, wenn man den Quellcde hat)


  • Enums mit manuellen Werten (type TMyEnum = (one, two=1, tree=7); ) fehlt in der die RTTI die Liste mit den Aufzählungswerten.
    Gut, das liegt vermutlich an der Art der Liste (#0-terminierte Stringliste), aber man hätte z.B. den fehlenden/übersprungenen Werten einen automatischen "Namen" verpassen können.
    (mein Vorschag wäre einfach eine Zahl, welche dem Wert entspricht, aber dieser "Fehler" existiert nun schon seit so vielen Jahrzehnten ... inzwischen ist das schon ein "Feature")


Vorallm der erste Punkt ist ein großes Problem, denn dort sind wirklich die grundlegenden RTTI-Rohdaten das Problem.
Außerdem wird ein Set, vorallem in der neuen RTTI, als "ordinaler" Typ behandelt, zusammen mit Enums, Integer und Chars, und das geht nunmal nur bis 8 Byte gut.
Die neue RTTI geht über TTypeData.OrdType, für die Größenbestimmung und da sind bei mehr als 8 Byte falsche/ungültige Werte enthalten.


Ein QC kommt demnächst. (erstmal sehn was sich noch für Fehler anfinden)



Meine Test-Daten, für den ersten Punkt:
Delphi-Quellcode:
type
  TMyEnum1 = 0..5; // 1 ... 8-1
  TMySet1 = set of TMyEnum1; // 1 Byte

  TMyEnum2 = 0..15; // 8 ... 16-1
  TMySet2 = set of TMyEnum2; // 2 Byte

  TMyEnum4 = 0..30; // 16 ... 32-1
  TMySet4 = set of TMyEnum4; // 4 Byte

  TMyEnum8 = 0..33; // 32 ... 64-1
  TMySet8 = set of TMyEnum8; // 8 Byte

  TMyEnum20 = 0..155; // ... 160-1
  TMySet20 = set of TMyEnum20; // 20 Byte

  TMyEnum32 = 0..250; // ... 256-1
  TMySet32 = set of TMyEnum32; // 32 Byte (multiple of 4)

  TMyEnum_1 = 0..$70;
  TMyEnum_2 = 0..$7F00;
  TMyEnum_4 = 0..$7FFF0000;
  TMyEnum_4u = 0..$FFFF0000;

  TMyClass = class abstract
    FField: Integer;
    FMyField1: TMySet1;
    FMyField2: TMySet2;
    FMyField4: TMySet4;
    FMyField8: TMySet8;
    FMyField32: TMySet32;
    FMyField_1: TMyEnum_1;
    FMyField_2: TMyEnum_2;
    FMyField_4: TMyEnum_4;
    FMyField_4u: TMyEnum_4u;
    function Getter(A, B: string; Index: Integer): TMySet4; virtual; abstract;
    procedure Setter(A, B: string; Index: Integer; Value: TMySet4); virtual; abstract;
    property X[A, B: string]: TMySet4 index 3 read Getter write Setter;
  published
    property I1: Integer index 1 read FField write FField default 3;
    property I2: Integer index 2 read FField write FField stored False ;
    property I3: Integer index 3 read FField write FField stored False default 3;
  end;
Und das, was man aus der RTTI auslesen kann: (als //-Kommentare sind die richtigen Werte enthalten, bzw. eine Erklärung)
Delphi-Quellcode:
// MinValue..MaxValue {TypeSize ClassName}

TMyEnum1 = {Integer}0..5; {Size=1 TRttiOrdinalType}

TMySet1 = set of TMyEnum1; {Size=1 OrdType=1=otUByte TRttiSetType}

TMyEnum2 = {Integer}0..15; {Size=1 TRttiOrdinalType}

TMySet2 = set of TMyEnum2; {Size=2 OrdType=3=otUWord TRttiSetType}

TMyEnum4 = {Integer}0..30; {Size=1 TRttiOrdinalType}

TMySet4 = set of TMyEnum4; {Size=4 OrdType=5=otULong TRttiSetType}

TMyEnum8 = {Integer}0..33; {Size=1 TRttiOrdinalType}

TMySet8 = set of TMyEnum8; {Size=1343671120 OrdType=255 TRttiSetType}
// SizeOf() = 8
// OrdType = invalid

TMyEnum20 = {Integer}0..155; {Size=1 TRttiOrdinalType}

TMySet20 = set of TMyEnum20; {Size=1 OrdType=1 TRttiSetType}
// SizeOf() = 20
// OrdType = invalid

TMyEnum32 = {Integer}0..250; {Size=1 TRttiOrdinalType}

TMySet32 = set of TMyEnum32; {Size=1 OrdType=1 TRttiSetType}
// SizeOf() = 32
// OrdType = invalid

TMyEnum_1 = {Integer}0..112; {Size=1 TRttiOrdinalType}

TMyEnum_2 = {Integer}0..32512; {Size=2 TRttiOrdinalType}

TMyEnum_4 = {Integer}0..2147418112; {Size=4 TRttiOrdinalType}

TMyEnum_4u = {Cardinal}0..-65536; {Size=4 TRttiOrdinalType}
// if MinValue > MaxValue then Cardinal

TMyClass = class {Package1.bpl Unit14.TMyClass Instance Size=4 TRttiInstanceType}
  public
    FField: Integer;
    FMyField1: TMySet1;
    FMyField2: TMySet2;
    FMyField4: TMySet4;
    FMyField8: TMySet8;
    FMyField32: TMySet32;
    FMyField_1: TMyEnum_1;
    FMyField_2: TMyEnum_2;
    FMyField_4: TMyEnum_4;
    FMyField_4u: TMyEnum_4u;
    function Getter(A: string; B: string; Index: Integer): TMySet4; virtual; {Index=0 Addr=$237B23D8}
    procedure Setter(A: string; B: string; Index: Integer; Value: TMySet4); virtual; {Index=1 Addr=$237B23E0}
    property X[A: string; B: string; Index: Integer]: TMySet4 read _Getter write _Setter;
    // TRttiIndexedProperty.ToString liefert für "X" nur eine "Zugriffsverletzung bei Adresse 6F687465. Lesen von Adresse 6F687465"
    // es sollte eigentlich "property X[A: string; B: string; Index: Integer]: TMySet4" liefern, was aber nicht am Set liegt
  published
    // für die Namen der Setter/Getter hab ich noch keine Übersetztung eingeaut
    property I1: Integer index 1 read _Field0004 write _Field0004 default 3;
    property I2: Integer index 2 read _Field0004 write _Field0004;
    property I3: Integer index 3 read _Field0004 write _Field0004 default 3;
  end;
$2B or not $2B

Geändert von himitsu ( 5. Mai 2014 um 09:10 Uhr)
  Mit Zitat antworten Zitat