Error while trying to access class attributes
Asked Answered
W

1

6

I have this class:

{$RTTI EXPLICIT FIELDS([vcProtected]) PROPERTIES([vcProtected])}
const
  PP_VEHICLE_FIELD = 'VEICULO_ID';
  PP_DRIVER_FIELD = 'MOTORISTA_ID';
  PP_TRIP_FIELD = 'VIAGEM_ID';
  PP_DATE = 'DATA';

type
  [TAttrDBTable('NONE')]
  TReportItem = class(TObject)
  protected
    [TAttrDBField(PP_VEHICLE_FIELD)]
    FVeiculoId: integer;
    [TAttrDBField(PP_DRIVER_FIELD)]
    FMotoristaId: integer;
    [TAttrDBField(PP_TRIP_FIELD)]
    FViagemId: integer;
    [TAttrDBField(PP_DATE)]
    FDataRelatorio: TDate;
  published
    class function GetTableName<T: class, constructor>: string;
  end.

class function TReportItem.GetTableName<T>: string;
var
  LRttiContext: TRttiContext;
  LRttiType: TRttiType;
  LCustomAttribute: TCustomAttribute;
  LType: T;
begin
  LType := T.Create;
  try
    LRttiContext := TRttiContext.Create;
    LRttiType := LRttiContext.GetType(LType.ClassType);
    for LCustomAttribute in LRttiType.GetAttributes do
      if LCustomAttribute is TAttrDBTable then
      begin
        Result := TAttrDBTable(LCustomAttribute).TableName;
        Break;
      end;
  finally
    LType.Free;
  end;
end;

I call it this way: TReportItem.GetTableName<TReportItem>; The <> can be any class that inherit TReportItem.

But, sometimes when I call: TReportItem.GetTableName in the command LRttiType.GetAttributes I get an access violation, sometimes not, depends of the 'compilation'. It works and stop working like magic. I don't know what is happening. Someone can give me a hint ?

The problem is on the GetAttributes, if I use that to get attributes in fiels, methods etc. It give me access violation. Is there some directive that I must to turn on or off to use it?

If I compile using Shift+F9, the GetAttributes give me AV, if I modify any line in the unit and compile using F9 GetAttributes works.

It's not only in my machine, other 8 programmers are with the same problem. Delphi XE.

The error occurs in this code in rtti.pas:

function FindCtor(AttrType: TRttiInstanceType; CtorAddr: Pointer): TRttiMethod;
type
  PPPointer = ^PPointer;
var
  p: PByte;
  imp: Pointer;
begin
  for Result in AttrType.GetMethods do
    if Result.CodeAddress = CtorAddr then
      Exit;
  // expect a package (i.e. DLL) import
  p := CtorAddr;
  Assert(p^ = $FF); // $FF $25 => indirect jump m32
  Inc(p);
  Assert(p^ = $25);
  Inc(p);
  imp := PPPointer(p)^^; //ERROR HAPPENS HERE
  for Result in attrType.GetMethods do
    if Result.CodeAddress = imp then
      Exit;
  Result := nil;
end;
Waechter answered 29/2, 2012 at 12:24 Comment(11)
Can you show your call to TReportItem.GetTableName.Jolo
When you get the AV, what value does LRttiType have?Jolo
@SaCi you wrote, you get AV when trying to get attributes for fields and properties but in code above getAttributes is used only to get class attributes. (if your fields and props are public, then seems to me, you have to inlclude vcPublic in $RTTI directive too)Peru
Yes, I'm debugging, in LRttiType I can access everything I want, fields (GetFields), methods(GetMethods) etc, but when I try to access the attributes it give me an av.Waechter
I solved the problem, but I didn't found the reason. I moved the unit to the begin in dpr and it works. So, some unit compilation should be causing the error. And for some reason the directives that I used didn't solve the problem. I'll try to find the true reason and post here.Waechter
By the way, your function doesn't need generics. If T is supposed to be a class that descends from TReportItem, then just call T.GetTableName. Within the function, replace T with Self. You can also replace LType.ClassType with Self. Declare LType as TReportItem.Farl
@SaCi, I have the same problem and I tried to move the unit as you, but the error persist, did you figure out what can cause this?Colleencollege
Yes Cesar, I did! Was a coding "error", make sure you have M+ directive on, and choose yours rtti directives correctly. If you need some extra help, e-mail me. RegardsWaechter
@SaCi the classes already have $M+, all this classes are specialized from TPersistent and to my classes I added: {$RTTI EXPLICIT PROPERTIES([vcPublic, vcPublished])}.Colleencollege
@CesarRomero e-mail me, [email protected], send the code or what you can. I can try help no problemWaechter
@SaCi, thank you for you offer, it seems to be a RTTI bug indeed, check this post #7202317 and the related QC qc.embarcadero.com/wc/qcmain.aspx?d=98261, and if you agree, could add some votes to bring more attention to the QC.Colleencollege
D
0

I had the exact same problem for hours today, same AV on imp := PPPointer(p)^^ in Rtti.pas.

I discovered that I used the same name for 2 attributes in 2 unrelated units in my project: after I renamed one of them, no more AV!

Directory answered 15/1, 2013 at 16:27 Comment(1)
I have the same problem and do not have attributes with same name I have also changed the unit inside the .dpr as @SaCi, but the error persistsColleencollege

© 2022 - 2024 — McMap. All rights reserved.