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;