procedure TForm1.Button1Click(Sender: TObject);
procedure TForm1.Button1Click(Sender: TObject);
begin
try
Form1:=TForm1.Create(nil);
Form1.ShowModal;
finally
FreeAndNil(Form1);
end;
end;
//---------------
everything works just fine at the first time when i click the button when i close it and click the button again i get access violation error at adress 00DB047D
... there is nothing in the OnCreate event for the Form1
... i checked the form if it nil after close it it's says nil
i don't know what i'm doing wrong ,for the record everything was working normal before
begin
try
Form1:=TForm1.Create(nil);
Form1.ShowModal;
finally
FreeAndNil(Form1);
end;
end;
//---------------
everything works just fine at the first time when i click the button when i close it and click the button again i get access violation error at adress 00DB047D
... there is nothing in the OnCreate event for the Form1
... i checked the form if it nil after close it it's says nil
i don't know what i'm doing wrong ,for the record everything was working normal before
You are freeing the form in a method of the form.
ReplyDeleteIt seems strange to show an instance of a form inside the method of that same form.
You are using the same variable Form1 for the main form and the secondary form created in the Button1Click event.
ReplyDeleteWhile that is certainly odd, it shouldn't result in an access violation, unless you access Form1 somewhere else.
Thomas Mueller Form1 is not the MainForm ,, yes i'm accessing the form1 from somewhere else lets say Form0 and Form0 isn't The MainForm too
ReplyDeleteNick Hodges what do you mean ? how should i free the form ?
ReplyDeleteYou should use a different variable than the default variable that the IDE provides for you:
ReplyDeleteprocedure TForm1.Button1Click(Sender: TObject);
var
MyForm: TForm1;
begin
try
MayForm:=TForm1.Create(nil);
MyForm.ShowModal;
finally
MyForm.Free;
end;
end;
Two points: (1) Never use FreeAndNil (2) Why are you creating a TForm1 inside a TForm1?
the same problem works just for the first time.
ReplyDelete(2) Why are you creating a TForm1 inside a TForm1?
...TForm1 inside a TForm1! i don't understand
I am assuming you just started using Delphi: Everytime a TFormX unit is created, a FormX: TFormX global var is also put in place for the IDE to manage automatic form creation. I am sure you are using that Form1 global form from inside your own Form1. Just have a check the advices you got above and check
ReplyDeleteJoaquin Menemene Not really i checked everything , what if i told you i have 32 Form creating in the same method and everyone of them works just fine expect this form .
ReplyDeleteNick Hodges I cannot see any bad thing about FreeAndNil in this context
ReplyDeleteHamza Benzaoui The resource protecting pattern is
ReplyDeletefoo := TFoo.Create;
try
// use foo
finally
foo.Free;
end;
your code can result in mystic operation
try
foo := TFoo.Create; // on exception here
// use foo
finally
foo.Free; // this will be called ... on what?
end;
and you should not use the global form variable to store a local instance. That is the root of your problem. The access violation is just a symptom
It was long time ago since we had FreeAndNil fight last time...
ReplyDeleteStop using global variables and then come back when you've removed them. Put the try after the resource acquisition.
ReplyDeleteWhen you encounter an error do some debugging. The biggest single weakness in beginners is an inability to debug. That's the next skill you need to acquire.
You wrote:
ReplyDeleteprocedure TForm1.Button1Click(Sender: TObject);
begin
try
Form1:=TForm1.Create(nil);
Form1.ShowModal;
1) Form1:= TForm1.Create(nil);
This is bad:
a) Form1 is a global. Stop using globals. Here a local scope avoids all confusions.
b) Form1 could very well be assigned since the event method is a method of TForm1. Now you create a leak.
2) Instead of writing
try
Form1:=TForm1.Create(nil);
finally
you must follow this pattern:
Form1:=TForm1.Create(nil);
try
// Some code
finally
This could be better implemented as a class function:
ReplyDeleteclass function TForm1.Execute: Boolean;
var
F: TForm1;
begin
F := TForm1.Create(nil);
try
Result := IsPositiveResult(F.ShowModal);
finally
F.Free;
end;
end;
I agree with the example of Alexander Elagin. Don't place the create inside the try and place it prior. Also, recommend removing the form unit's global Var for the form1: tform1; so that it reinforces use of localized var for form and possible "monkey business" accessing the global from other units.
ReplyDeleteIn fact, when I create a new form, the first thing I do is delete the global variable.
Thanks a lot guys i figure it out ,, i was referencing to this form in somewhere else i totally forgot it..David Heffernan i know some debugging skills but when it comes to variables and pointers i always get lost and have been avoiding it , but i thinks i should make some time for it . is there any books you can recommend for a deep dive in debugging will be so useful for me thanks in advance :)
ReplyDeleteHamza Benzaoui Treat the pointer/reference as a vcard. The variable can hold a vCard (value) and the vcard is pointing to a person/address (instance).
ReplyDelete