Thanks a lot to Bart, wp and RAW for your new replies and your help. I will answer them again one by one to avoid posts that get too long.
Your Abort Button (name: BTN I think) closes the form.
At that point the form gets freed (because you set ClosAction to caFree), but not nilled.
You then break the loop in the main form and call free_Memo(FormMM);
This will call Free on an already destroyed form, hence the AV.
OK, now I understand what you mean. Thanks for clarification.
This explains, why the AV occurs, if the Abort-Button had been pressed.
But if the Abort-Button was
not pressed, I call FormMM.Close() instead in line 46 =
if memoopen then FormMM.Close; {only if not already closed by ABORT-Button}and in this case the AV does
not occur later in free_Memo() in line 48...
I don't understand the difference. In
both cases FormMM.Close(), which calls CloseMM(), is exactly called once (as we see in the Console output). Why does the variant
without Abort-Button work (where FormMM.Close() is called once in line 46 of Unit1) and the variant
with Abort-Button does not (where FormMM.Close() is called once in line 57 of unit LCL_lib)?
And pleasae notice, that if the Abort-Button is pressed, that in this case Application.ComponentCount is reduced to 1, while if the Abort-Button is not pressed, Application.ComponentCount stays at 2. Who (and why) reduces Application.ComponentCount in just this case, where later the AV occurs?
This is as far as I cab understand the code flow, without an actual compilable example.
I attached a compilable demo at my 1st post, did you see it?
Add a debug statement in the destructor of this form, so you can see when it is called, my guess is before you call free_memo(FormMM).
That sounds interesting. I was not sure, what you meant exactly: add a destructor to 'TFormMM' and hope that it's called automatically or add an OnDestroy-Event? I tried the latest:
procedure TFormMM.show_Memo(...);
begin
...
OnDestroy:=@FormDestroy;
...
end;
procedure TFormMM.FormDestroy(Sender: TObject);
begin
writeln('FormDestroy()');
end;
And I added a writeln() in free_Memo() and a 3rd writeln() of memoopen and Application.ComponentCount in line 48 of Unit1, after free_Memo() was called.
Now the Console output
without Abort-Button is:
1) memoopen=TRUE ComponentCount=2
CloseMM(): ComponentCount=2
2) memoopen=FALSE ComponentCount=2
free_Memo()
FormDestroy()
3) memoopen=FALSE ComponentCount=1and
with Abort-Button is:
Memo_Button_Click() called
CloseMM(): ComponentCount=2
FormDestroy()
1) memoopen=FALSE ComponentCount=1
2) memoopen=FALSE ComponentCount=1
free_Memo()
TApplication.HandleException Access violationFrom my understanding:
- in the 2nd case, with Abort-Button, FormDestroy() seems to be called
automatically by CloseMM()
- but in the 1st case, without Abort-Button, the same CloseMM() does
not call FormDestroy() automatically - it is called much later by free_Memo().
This seems to explain, why 1st case works and 2nd case not.
So my Questions to this are: - But why does CloseMM() react so different?
- If we could understand this behavior, it might be very
easy to add a Flag, which is set in Memo_Button_Click(), and in free_Memo() we simply skip the FreeAndNil(), if this Flag is set and everything is happy?
- Or can we delete free_Memo()
completely, because of 'CloseAction:=caFree', as rvk suggested in reply #8 and wp in reply #13? Would this be safe and clean, even if the dynamic Memo-Form is opened and closed
multiple times, before the main program terminates? Do you agree to this?