Reputation: 9431
I defined a type for set of Byte, an interface and a class that implements the interface. The interface has a property of type TTestSetofByte + getter and setter. Nothing special at all.
type
TTestSetOfByte = set of Byte;
ITestInterface = interface
['{BCF0CEC2-F999-4E8A-A732-416F343C1629}']
function GetPropSetOfByte: TTestSetOfByte;
procedure SetPropSetOfByte(const Value: TTestSetOfByte);
property PropSetOfByte: TTestSetOfByte read GetPropSetOfByte write SetPropSetOfByte;
end;
TTestClass3 = class(TInterfacedObject, ITestInterface)
private
FSetOfByte: TTestSetOfByte;
function GetPropSetOfByte: TTestSetOfByte;
procedure SetPropSetOfByte(const Value: TTestSetOfByte);
public
constructor Create;
property PropSetOfByte: TTestSetOfByte read GetPropSetOfByte write SetPropSetOfByte;
end;
The problem is that when I try to read the Value of the PropSetOfByte property delphi throws an EAccessViolation and I do not understand why. Properties of other types(int, string) work just fine.
Here is the test code:
procedure TTestUtlRttiComparer.DeleteMe;
var
i: Integer;
Instance1: ITestInterface;
Object1: TObject;
RttiContext: TRttiContext;
RttiProp: TRttiProperty;
RttiValue1: TValue;
Type1: TRttiType;
begin
Instance1 := TTestClass3.Create;
Check(Instance1.PropSetOfByte = [1,4], 'Making sure getter works!');
Instance1.PropSetOfByte := [3,4];
Check(Instance1.PropSetOfByte = [3,4], 'Making sure setter works!');
Object1 := (Instance1 as TObject);
Check(Assigned(Object1));
RttiContext := TRttiContext.Create;
try
Type1 := RttiContext.GetType(Object1.ClassInfo);
// Properties pruefen
for i := 0 to High(Type1.GetProperties) do
begin
RttiProp := Type1.GetProperties[i];
if RttiProp.Name = 'PropSetOfByte' then
begin
RttiValue1 := RttiProp.GetValue(Object1); // THIS CHECK FAILS with EACESSVIOLATION!!!
end;
end;
finally
RttiContext.Free;
end;
end;
I am using XE-2.
Thank you!
Upvotes: 0
Views: 1224
Reputation: 598309
It crashes when TRttiType.GetValue()
(more specifically, the Invoke()
function in the System.Rtti
unit) tries to call TTestClass3.GetPropSetOfByte()
. The correct Self
pointer is being passed in, but the Result
parameter is nil, so a crash occurs when GetPropSetOfByte()
tries to assign FSetOfByte
to Result
.
In short, the call stack is not being setup correctly by the RTTI system for Set
-based properties. I have reproduced the crash in XE2, XE6, and XE7, and have filed a bug report with Embarcadero:
TRttiProperty.GetValue() crash on Set-based property https://quality.embarcadero.com/browse/RSP-10206
Upvotes: 3