Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Attempt to access value of Attribute on method is giving AV Error



Permlink Replies: 6 - Last Post: Feb 16, 2015 10:31 AM Last Post By: Adam Brett
Adam Brett

Posts: 9
Registered: 11/18/04
Attempt to access value of Attribute on method is giving AV Error
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 3, 2015 5:01 AM
I have already posted this message on Delphi Non-tech, but it has been suggested I post it here. I have started trying to use Attributes with RTTI in Delphi (XE2 Enterprise), but when I do I get an AV.

--

I have the following Attribute declaration:

ImageIndexAttribute = class(TCustomAttribute)
public
Value: Integer;
constructor Create(aImageIndex: Integer);
end;

and the following class:

TEmailPanel = class(TabActionPanel)
published
[ImageIndexAttribute(6)]
procedure New_Email;
end;

(Note that ActionPanel is a pretty simple TPanel descendent)

When I call the following method I get an AV at the indicated line:

procedure TabActionPanel.LoadPublishedMethods;
var
rttiCont: TRttiContext;
rttiMethod : TRttiMethod;
rttiAttri: TCustomAttribute;
aImageIndex: Integer;
begin
//debug line below just proves that a button can be added
AddButton('Test',
60,
ButtonClick);
rttiCont:= TRttiContext.Create;
rttiType:= rttiCont.FindType('uActionPanel.' + Self.ClassName);
for rttiMethod in rttiType.GetMethods do
if POS('_', rttiMethod.Name)>0 then
begin
try
//in my code error occurs here:
for rttiAttri in rttiMethod.GetAttributes do
if rttiAttri is ImageIndexAttribute then
aImageIndex:= ImageIndexAttribute(rttiAttri).Value;
except
aImageIndex:= 1;
end;
AddButton(StringReplace(rttiMethod.Name, '_', ' ', [rfReplaceAll]),
aImageIndex,
ButtonClick);
end;
end;

--

The whole test project is a single form. I include the full code for this form below. Note that the form is completely blank, and the only method on it is the "FormCreate".

unit uActionPanel;

{$RTTI EXPLICIT METHODS ([vcPublished])}
{$METHODINFO ON}

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls,

//RTTI BITS Delphi 2010 or XE2
System.Rtti, System.TypInfo,
//mine
uLookups,
uToolbar;

type
ImageIndexAttribute = class(TCustomAttribute)
public
Value: Integer;
constructor Create(aImageIndex: Integer);
end;

type
TabActionPanel = class(TPanel)
strict private
ButtonTop: Integer;
FTitle: string;
rttiCont: TRttiContext;
rttiType: TRttiType;
procedure AddButton(const aCaption: string; aTag: Integer; aClick:
TNotifyEvent);
procedure SetTitle(const Value: string);
procedure TestClick(Sender: TObject);
strict protected
procedure ButtonClick(Sender: TObject);
public
Toolbar: TabToolbar;
property Title: string read FTitle write SetTitle;
constructor Create(aOwner : TWinControl); overload;
procedure LoadPublishedMethods;
end;

TEmailPanel = class(TabActionPanel)
published
[ImageIndexAttribute(6)]
procedure New_Email;
end;

TActionPanelTestingForm = class(TForm)
procedure FormCreate(Sender: TObject);
strict private
Panel: TEmailPanel;
end;

var
ActionPanelTestingForm: TActionPanelTestingForm;

implementation

uses
Vcl.StdCtrls;

{$R *.dfm}

constructor ImageIndexAttribute.Create(aImageIndex: Integer);
begin
Value:= aImageIndex;
end;

constructor TabActionPanel.Create(aOwner : TWinControl);
begin
inherited create(aOwner);
Parent:= aOwner;
ButtonTop:= 10;
end;

procedure TabActionPanel.AddButton(const aCaption: string; aTag: Integer;
aClick: TNotifyEvent);
var
aButton: TButton;
begin
aButton:= TButton.Create(self);
aButton.Parent:= self;
aButton.Top:= ButtonTop;
aButton.Tag:= aTag;
ButtonTop:= ButtonTop + aButton.Height + 10;
aButton.Left:= 10;
aButton.Width:= 200;
aButton.Caption:= aCaption;
aButton.OnClick:= aClick;
end;

procedure TabActionPanel.LoadPublishedMethods;
var
rttiCont: TRttiContext;
rttiMethod : TRttiMethod;
rttiAttri: TCustomAttribute;
aImageIndex: Integer;
begin
//debug line below just proves that a button can be added
AddButton('Test',
60,
ButtonClick);
rttiCont:= TRttiContext.Create;
rttiType:= rttiCont.FindType('uActionPanel.' + Self.ClassName);
for rttiMethod in rttiType.GetMethods do
if POS('_', rttiMethod.Name)>0 then
begin
try
//in my code error occurs here:
for rttiAttri in rttiMethod.GetAttributes do
if rttiAttri is ImageIndexAttribute then
aImageIndex:= ImageIndexAttribute(rttiAttri).Value;
except
aImageIndex:= 1;
end;
AddButton(StringReplace(rttiMethod.Name, '_', ' ', [rfReplaceAll]),
aImageIndex,
ButtonClick);
end;
end;

procedure TabActionPanel.ButtonClick(Sender: TObject);
begin
Showmessage('Clicked. Object Tag = ' + IntToStr((Sender as TButton).Tag));
end;

procedure TabActionPanel.SetTitle(const Value: string);
begin
FTitle := Value;
Toolbar.Title:= Value;
end;

procedure TabActionPanel.TestClick(Sender: TObject);
begin
Showmessage('Hello World');
end;

procedure TActionPanelTestingForm.FormCreate(Sender: TObject);
begin
Caption:= gLU.ClassNameToTitle(ClassName);
Panel:= TEmailPanel.Create(self);
Panel.Align:= alClient;
Panel.LoadPublishedMethods;
end;

procedure TEmailPanel.New_Email;
begin
Showmessage('Create a new email');
end;

END.

Marek Bojarski

Posts: 29
Registered: 11/26/01
Re: Attempt to access value of Attribute on method is giving AV Error
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 3, 2015 1:50 PM   in response to: Adam Brett in response to: Adam Brett
W dniu 2015-02-03 o 14:01, Adam Brett pisze:
I have already posted this message on Delphi Non-tech, but it has been suggested I post it here. I have started trying to use Attributes with RTTI in Delphi (XE2 Enterprise), but when I do I get an AV.

--

I have the following Attribute declaration:

ImageIndexAttribute = class(TCustomAttribute)
public
Value: Integer;
constructor Create(aImageIndex: Integer);
end;

and the following class:

TEmailPanel = class(TabActionPanel)
published
[ImageIndexAttribute(6)]
procedure New_Email;
end;

(Note that ActionPanel is a pretty simple TPanel descendent)

When I call the following method I get an AV at the indicated line:

procedure TabActionPanel.LoadPublishedMethods;
var
rttiCont: TRttiContext;
rttiMethod : TRttiMethod;
rttiAttri: TCustomAttribute;
aImageIndex: Integer;
begin
//debug line below just proves that a button can be added
AddButton('Test',
60,
ButtonClick);
rttiCont:= TRttiContext.Create;
rttiType:= rttiCont.FindType('uActionPanel.' + Self.ClassName);
for rttiMethod in rttiType.GetMethods do
if POS('_', rttiMethod.Name)>0 then
begin
try
//in my code error occurs here:
for rttiAttri in rttiMethod.GetAttributes do
if rttiAttri is ImageIndexAttribute then
aImageIndex:= ImageIndexAttribute(rttiAttri).Value;
except
aImageIndex:= 1;
end;
AddButton(StringReplace(rttiMethod.Name, '_', ' ', [rfReplaceAll]),
aImageIndex,
ButtonClick);
end;
end;

Your code makes an assumption that any method in your class with '_' in
name will have attributes, which may not be true.

I guess you should check rttiMethod.GetAttributes for nil before loop.
Adam Brett

Posts: 9
Registered: 11/18/04
Re: Attempt to access value of Attribute on method is giving AV Error
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 6, 2015 8:53 AM   in response to: Marek Bojarski in response to: Marek Bojarski
Dear Marek

Thank you for your answer.

The line:

if POS('_', rttiMethod.Name)>0 then

Is intentional. I only want to do the search if the method-name includes an under-score. This is a simple hack to allow me to select which methods are picked out by this code. In this case the class only has 1 method, and that method does include an underscore, so the error is not occurring due to this line.

If I change my code as you suggest:

for rttiAttri in rttiMethod.GetAttributes do
if (rttiAttri <> nil) and (rttiAttri is ImageIndexAttribute) then
aImageIndex:= ImageIndexAttribute(rttiAttri).Value;

adding the "if (rttiAttri <> nil)" segment, I still get the Access Violation.

The Violation occurs on the previous line.

rttiMethod.GetAttributes returns an error:

"Access violation at 00525A1C accessing F4C483EC"

rttiMethod is NOT nil, I can access the rttiMethod.Name property, and return the name successfully.

However rttiMethod.GetAttributes creates an error, even though I have marked the method with an attribute, as shown in the code.

I am really confused by this, as what I am doing is (by the standards of RTTI!) very simple indeed, but I cannot get it to run.

Any help gratefully received!
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Attempt to access value of Attribute on method is giving AV Error
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 7, 2015 4:20 PM   in response to: Adam Brett in response to: Adam Brett
Adam wrote:

I only want to do the search if the method-name includes an under-score.
This is a simple hack to allow me to select which methods are picked out
by this code.

Sounds like something you should be using attributes for that.

for rttiAttri in rttiMethod.GetAttributes do
if (rttiAttri <> nil) and (rttiAttri is ImageIndexAttribute) then

rttiAttri will never be nil inside the loop, but GetAttributes() can return
nil.

The Violation occurs on the previous line.

rttiMethod.GetAttributes returns an error:

"Access violation at 00525A1C accessing F4C483EC"

rttiMethod is NOT nil, I can access the rttiMethod.Name property, and
return the name successfully.

However rttiMethod.GetAttributes creates an error, even though I have
marked the method with an attribute, as shown in the code.

You are going to have to debug into the RTL to find out what is actually
failing. This sounds like a bug in the RTTI system to me.

--
Remy Lebeau (TeamB)
Marek Bojarski

Posts: 29
Registered: 11/26/01
Re: Attempt to access value of Attribute on method is giving AV Error
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 9, 2015 11:07 PM   in response to: Adam Brett in response to: Adam Brett
W dniu 2015-02-06 o 17:53, Adam Brett pisze:
Dear Marek

Thank you for your answer.

The line:

if POS('_', rttiMethod.Name)>0 then

Is intentional. I only want to do the search if the method-name includes an under-score. This is a simple hack to allow me to select which methods are picked out by this code. In this case the class only has 1 method, and that method does include an underscore, so the error is not occurring due to this line.

If I change my code as you suggest:

for rttiAttri in rttiMethod.GetAttributes do
if (rttiAttri <> nil) and (rttiAttri is ImageIndexAttribute) then
aImageIndex:= ImageIndexAttribute(rttiAttri).Value;

adding the "if (rttiAttri <> nil)" segment, I still get the Access Violation.

The Violation occurs on the previous line.

rttiMethod.GetAttributes returns an error:

"Access violation at 00525A1C accessing F4C483EC"

rttiMethod is NOT nil, I can access the rttiMethod.Name property, and return the name successfully.

However rttiMethod.GetAttributes creates an error, even though I have marked the method with an attribute, as shown in the code.

I am really confused by this, as what I am doing is (by the standards of RTTI!) very simple indeed, but I cannot get it to run.

Any help gratefully received!

There are some methods with underscore in the name in class hierarchy
like _AddRef. Your class can have one of them inherited.
To test this just list all method names or use debugger to look what
function names get passed the underscore test.
Check for rttiMethod.GetAttributes=nil before the loop.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: Attempt to access value of Attribute on method is giving AV Error
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 10, 2015 10:17 AM   in response to: Marek Bojarski in response to: Marek Bojarski
Marek wrote:

There are some methods with underscore in the name in class
hierarchy like _AddRef. Your class can have one of them inherited.
To test this just list all method names or use debugger to look
what function names get passed the underscore test.

You can also use rttiType.GetDeclaredMethods() instead of rttiType.GetMethods()
if you want to ignore inherited methods.

--
Remy Lebeau (TeamB)
Adam Brett

Posts: 9
Registered: 11/18/04
Re: Attempt to access value of Attribute on method is giving AV Error
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 16, 2015 10:31 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy and Marek,

Thank you for these answers ... I have been busy with other projects, so I have only just seen them.

To test this just list all method names or use debugger to look what
function names get passed the underscore test.
Check for rttiMethod.GetAttributes=nil before the loop.

The issue is that rttiMethod.GetAttributes generates the error. Therefore the line:

if rttiMethod.GetAttributes <> nil then

generates an error. How can I assess whether rttiMethod.GetAttributes is nil without calling it and generating the error?

You can also use rttiType.GetDeclaredMethods() instead of rttiType.GetMethods()
if you want to ignore inherited methods.

I have changed my code to this form, but it does not seem to have changed the situation. Thank you for this recommendation though, as it improves the code.
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02