[Solved] Access Violation While Calling Form’s Method


In your question you left out a very important piece of the puzzle. You’ve mentioned it in comments, but I repeat it here because it’s the direct trigger of your problem. In comments you said the form is created as follows:

with TForm1.Create(Self) do
begin
  try
    ShowModal;
  finally
    Free;
  end;
end;

Your problem is that within the call-chain of ShowModal you expect Form1 to be assigned specifically to the instance you’ve just created. But clearly you haven’t yet done anything to set Form1.

Your “solution” was to assign Form1 within the ShowModal call-chain. While this solves your immediate problem, it is far from correct, and I’ll explain why later. First I’ll show the simple solution that would have avoided the problem altogether (note it’s not a complete solution because there are far more problems with your code than you realise).

Solution, get rid of with:

//This first line is the most important.
//It explicitly sets which variable must be assigned to the new form.
Form1 := TForm1.Create(Self);
try
  Form1.ShowModal;
finally
  Form1.Free;
end;

Vishal, try it out. If you do, you’ll see it works. And hopefully I have your full attention now. You didn’t believe at first, but perhaps you now realise I really do understand correctly.


So why do I say your “solution” wrong? After all it seems to solve the problem….

Well, you said it yourself: you expected Form1 to be assigned at the start of FormShow. You’re right, it should be. By assigning Form1 := Self; inside FormShow you’re just patching up the earlier mistake. Surely you agree it’s better to fix the original mistake than to just patch over it later?

But there’s a deeper problem here… I’m not sure you understand the difference between “object instances” and “classes”. (If you do, then please still read the next few paragraphs for revision.)

It seems you expected that when TForm1 was created it should be automatically assigned to the Form1 variable. It’s as if you expected there would only ever be one TForm1 in memory at any point in time. But TForm1 is a class type; meaning it generally defines the behaviour for any number of object instances of the same type. Each time you create a TForm1, it’s a new separate instance of the form. And each instance can have its own variable that is assigned to it. E.g.

JohnsForm1 := TForm1.Create(Self);
PaulsForm1 := TForm1.Create(Self);

Consider for a moment what happens with your incorrect “solution” if you needed 2 form variable? What would you write inside the FormShow method? JohnsForm1 := Self; or PaulsForm1 := Self;?

Of course you can still choose to keep only 1 instance of TForm1 in memory at a time. But Delphi has no way to automatically know that is what you intend. So you should still do any desired assignments explicitly as above.


I mentioned there are still more serious problems with your code. It’s related to the above discussion about object instance and class types.

Your TTest class makes a bunch of unnecessary assumptions:

  • It assumes there will only ever be 1 instance of TForm1.
  • It assumes the form will always be available when needed.
  • And it assumes the form will be assigned to the Form1 variable.

So again, if you need a JohnsForm1 and a PaulsForm1, your code won’t work.

A tiny change to TTest.LoadMyData and TForm1.FormShow solves these problems.

//Write LoadMyData so it can be told which form instance to load the data into
procedure TTest.LoadMyData(ALoadForm: TForm1);
begin
  ALoadForm.LoadData;
end;

//Change FormShow to tell Test which form to use in LoadMyData
procedure TForm1.FormShow(Sender: TObject);
begin
  Initilize;
  Test := TTest.Create;
  Test.LoadMyData(Self);
end;

For the record, David already gave you this information in his answer. His answer also demonstrates the proper resource protection for the new TTest instance, whereas I’ve left it out for the sake of simplicity.

By the way, these 2 little changes would have also solved your problem.
Basically, you had 2 mistakes in your code. The combination of both mistakes caused your problem.
You can fix either one to make the problem go away. But you should fix both to make your code better.

6

solved Access Violation While Calling Form’s Method