Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

EAccessViolation when accessing an object from an event that has been called from it's constructor

Posted on 2002-03-18
2
Medium Priority
?
205 Views
Last Modified: 2010-04-05
Hi,

I have a class and sometimes an event can be fired from within the constructor itself, so I allow the event property to be set with a parameter in the constructor.  The problem is that in the event, accessing the StringList gives an EAccessViolation, even though the StringList itself has been created before the event is called.  I can access the StringList within Create though.

The code below demonstrates the problem.  Do you know of any way to get around this problem?

Thanks,

Richard



unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Unit2;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }

    Test: TTest;

    procedure TestEvent(i: Integer);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Test := TTest.Create(TestEvent);
  Test.Free;
end;

procedure TForm1.TestEvent(i: Integer);
begin
  // This line causes the access violation

  ShowMessage(IntToStr(Test.StringList.Count));
end;

end.

unit Unit2;

interface

uses
  classes;

type TOnTestEvent = procedure(i: Integer) of object;

type
  TTest = class
  private
    FOnTestEvent: TOnTestEvent;
  public
    StringList: TStringList;

    property OnTestEvent: TOnTestEvent read FOnTestEvent write FOnTestEvent;

    constructor Create(AOnTestEvent: TOnTestEvent);
    destructor Destroy; override;
  end;

implementation

uses
  Dialogs, SysUtils;

constructor TTest.Create(AOnTestEvent: TOnTestEvent);
begin
  OnTestEvent := AOnTestEvent;

  StringList := TStringList.Create;

  // The StringList can be accessed here okay with no problems

  ShowMessage(IntToStr(StringList.Count));

  if Assigned(FOnTestEvent) then FOnTestEvent(1);
end;

destructor TTest.Destroy;
begin
  StringList.Free;
end;

end.
0
Comment
Question by:Richard2000
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
2 Comments
 

Expert Comment

by:Kelmi
ID: 6878488
Reason is that the 'Test' member is still nil when you call it from the TestEvent procedure.

 ShowMessage(IntToStr(Test.StringList.Count)); // Test is still nil because it hasn't been created yet
0
 
LVL 14

Accepted Solution

by:
AvonWyss earned 200 total points
ID: 6879171
What Kelmi is sying is in fact the problem. The variable Test is only being assigned the constructed object when the constructor has successfully terminated. Therefore, Test is not assigned until after the constructor. To work around this, do it like this:

Unit1:

procedure TForm1.TestEvent(Sender: TObject; i: Integer);
begin
    ShowMessage(IntToStr((Sender as TTest).StringList.Count));
end;

Unit2:

type
    TOnTestEvent = procedure(Sender: TObject; i: Integer) of object;

constructor TTest.Create(AOnTestEvent: TOnTestEvent);
begin
    OnTestEvent := AOnTestEvent;
    StringList := TStringList.Create;
    ShowMessage(IntToStr(StringList.Count));
    if Assigned(FOnTestEvent) then
        FOnTestEvent(self,1);
end;

It's a good idea to include the Sender anyways since this allows you to have mutliple objects launch the same event without loosing knowledge of which object did fire the event.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…
Suggested Courses

618 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question