BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

FormResize() being called after my form's destructor
Goto page 1, 2  Next
 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (VCL Components Usage)
View previous topic :: View next topic  
Author Message
Joseph F. Muscarella
Guest





PostPosted: Thu Dec 11, 2003 1:13 pm    Post subject: FormResize() being called after my form's destructor Reply with quote



When I close my program, I am getting an error (Access violation). When
tracking it down, I discovered that the FormResize method was being called
after my form's destructor had already executed. This should not be
allowed, because my form is invalid at this point and any work done by
FormResize() could be catastrophic (and obviously is.)

I know that OnDestroy should be avoided due to problems like this, but does
that apply also to FormResize? Or is this due to some obscure error in my
program that I haven't yet discovered. I thought I would check here first.

Thanks,
Joe


Back to top
Vladimir
Guest





PostPosted: Thu Dec 11, 2003 3:49 pm    Post subject: Re: FormResize() being called after my form's destructor Reply with quote



Quote:
When I close my program, I am getting an error (Access violation). When
tracking it down, I discovered that the FormResize method was being called
after my form's destructor had already executed

I also noticed that. I avoid 'Access Violations' by checking my pointers:

if ( MyPointer != NULL )
DoTask();
else
ViolationAvoided();

.... but be sure to initialize MyPointer to NULL after destruction:
delete MyPointer;
MyPointer = NULL;

I would like also to hear why is this event fired.

Vladimir.





Back to top
Joseph F. Muscarella
Guest





PostPosted: Thu Dec 11, 2003 4:00 pm    Post subject: Re: FormResize() being called after my form's destructor Reply with quote



Quote:
if ( MyPointer != NULL )
DoTask();
else
ViolationAvoided();

... but be sure to initialize MyPointer to NULL after destruction:
delete MyPointer;
MyPointer = NULL;

Yes, but the problem here is that if MyPointer is a member of my Form, then
after the form's destructor finishes, the memory used by MyPointer is
invalid. Checking this memory location in the OnResize method is therefore
invalid. Although it may work sometimes (if that memory hasn't been reused
yet), it is not guaranteed to work and will probably result in very bad
things.

On the other hand, if MyPointer (or some other simple flag like a bool) is
declared globally static, then I guess it would work.

For what it's worth, I got around this by unhooking the OnResize event
handler in my destructor:

OnResize = NULL;

This is a kludge, but it works. I think the VCL has a bug.

Joe



Back to top
Vladimir
Guest





PostPosted: Thu Dec 11, 2003 4:07 pm    Post subject: Re: FormResize() being called after my form's destructor Reply with quote

Quote:
Yes, but the problem here is that if MyPointer is a member of my Form,
then
after the form's destructor finishes, the memory used by MyPointer is
invalid.

That's much bigger problem. My pointers were global, because they are
defined and declared before main form construction...

Quote:
For what it's worth, I got around this by unhooking the OnResize event
handler in my destructor:

OnResize = NULL;

This is a kludge, but it works. I think the VCL has a bug.


I use initializing events with NULL very often to avoid some recursive
calls.




Back to top
JD
Guest





PostPosted: Thu Dec 11, 2003 8:24 pm    Post subject: Re: FormResize() being called after my form's destructor Reply with quote


"Joseph F. Muscarella" <joe (AT) infosight-DISCARDMUNG- (DOT) com> wrote:
Quote:
[...] I think the VCL has a bug.

AFAIK there are no problems with the OnResize event. Please
show both OnResize and the dtor.

~ JD


Back to top
Vladimir Stefanovic
Guest





PostPosted: Thu Dec 11, 2003 9:58 pm    Post subject: Re: FormResize() being called after my form's destructor Reply with quote

Quote:
AFAIK there are no problems with the OnResize event. Please
show both OnResize and the dtor.

Some problem definitely exists!

The code of mine is very complex but I'll try to extract some code
skeleton that reproduces the problem (tonight or maybe tomorrow).
Now, just some notes...

On some machines 'Access Violation' does not appear as a message (?!).
But if the project is build with CodeGuard the problem can be seen very
precisely in the CodeGuards Log (*.cgl) file.

Beleave me I'll never use the below condition ( Cfg != 0 ) if it's not
needed.

void __fastcall TInitialForm::FormResize(TObject *Sender)
{
// ...
bool result;
if ( Cfg != 0 ) //
{
result = Cfg->Get( SomeArgs );
}
else
{
ForgetResultAndGoHome();
return;
}
// ...
}

Vladimir.




Back to top
Joseph F. Muscarella
Guest





PostPosted: Fri Dec 12, 2003 2:47 pm    Post subject: Re: FormResize() being called after my form's destructor Reply with quote

Quote:
AFAIK there are no problems with the OnResize event. Please
show both OnResize and the dtor.

__fastcall TMainForm::~TMainForm()
{
DisplayPrefs dprefs = Preferences::Instance()->Get_display_prefs();
dprefs.state = WindowState;
dprefs.top = Top;
dprefs.left = Left;
Preferences::Instance()->Set_display_prefs(dprefs);

delete Preferences::Instance();
}


void __fastcall TMainForm::FormResize(TObject *Sender)
{
term_rows = ImagePanel->Height / row_height;
term_cols = (Width / col_width) - 1;
display_rows = term_rows / 4;
display_chars = display_rows * term_cols;

Show_page();
}

Using the debugger, I placed a breakpoint in both the destructor and in the
FormResize function. When the form is closed, the destructor breakpoint is
hit first, then the FormResize breakpoint. When my Show_page() function is
called, the Access Violation happens.

If I add

OnResize = NULL;

in my destructor, the problem goes away.

BTW, I am using BCB 5 Enterprise.

Regards,
Joe



Back to top
Boba
Guest





PostPosted: Fri Dec 12, 2003 6:16 pm    Post subject: Re: FormResize() being called after my form's destructor Reply with quote

"Joseph F. Muscarella" <joe (AT) infosight-DISCARDMUNG- (DOT) com> wrote

Quote:
if ( MyPointer != NULL )
DoTask();
else
ViolationAvoided();

... but be sure to initialize MyPointer to NULL after destruction:
delete MyPointer;
MyPointer = NULL;

Yes, but the problem here is that if MyPointer is a member of my Form,
then
after the form's destructor finishes, the memory used by MyPointer is
invalid. Checking this memory location in the OnResize method is
therefore
invalid. Although it may work sometimes (if that memory hasn't been
reused
yet), it is not guaranteed to work and will probably result in very bad
things.
MyPointer will become invalid only if you free it explicitly in the Form's

destructor; otherwise the memory it points to will become hard to access
(unless you've made a copy of that pointer) but the memory will not get
freed (memory leak). If this is a case, "checking this memory location in
the OnResize method is therefore invalid" because the OnResize method
itself is not accessible, but not the memory location pointed by MyPointer.
If MyPointer points to a memory location inside the Form, then the story
is different and there will be no memory leak after Form's destruction:
class TMyForm{ int I[10], *MyPointer; };
TMyForm *Form=new TMyForm;
Form->MyPointer=new int[10];
delete Form;//memory leak
*Form=new TMyForm;
Form->MyPointer=Form->I;
delete Form;//no leak

//Boba




Back to top
Joseph F. Muscarella
Guest





PostPosted: Fri Dec 12, 2003 7:07 pm    Post subject: Re: FormResize() being called after my form's destructor Reply with quote

Quote:
MyPointer will become invalid only if you free it explicitly in the Form's
destructor; otherwise the memory it points to will become hard to access
(unless you've made a copy of that pointer) but the memory will not get
freed (memory leak). If this is a case, "checking this memory location in
the OnResize method is therefore invalid" because the OnResize method
itself is not accessible, but not the memory location pointed by
MyPointer.
If MyPointer points to a memory location inside the Form, then the story
is different and there will be no memory leak after Form's destruction:
class TMyForm{ int I[10], *MyPointer; };
TMyForm *Form=new TMyForm;
Form->MyPointer=new int[10];
delete Form;//memory leak
*Form=new TMyForm;
Form->MyPointer=Form->I;
delete Form;//no leak

Yes, but as I said, if MyPointer is a member of my Form (not necessarily
owned by the form - perhaps a pointer to char or something, not part of the
VCL), when the form's destructor executes then the memory used by the form
is not valid. Therefore, you cannot access MyPointer, even from outside
the class if it were public , because the Form no longer exists and its
"this" is invalid. You are right about the memory leak if MyPointer is
not owned by the Form and the destructor does not free it.

Joe



Back to top
JD
Guest





PostPosted: Fri Dec 12, 2003 7:09 pm    Post subject: Re: FormResize() being called after my form's destructor Reply with quote


"Joseph F. Muscarella" <joe (AT) infosight-DISCARDMUNG- (DOT) com> wrote:
Quote:
[...]When the form is closed, the destructor breakpoint is
hit first, then the FormResize breakpoint. When my Show_page()
function is called, the Access Violation happens.

Obviousely, Show_Page is causing the AV. Without seeing the
code to determine if there is a better way or place for
Show_Page, you're doing the best that you can with it. The
only other option is to use a global flag that you set in the
dtor and test for in the FormResize.

~ JD


Back to top
Boba
Guest





PostPosted: Fri Dec 19, 2003 11:13 pm    Post subject: Re: FormResize() being called after my form's destructor Reply with quote

"Joseph F. Muscarella" <joe (AT) infosight-DISCARDMUNG- (DOT) com> wrote

Quote:
...
Yes, but as I said, if MyPointer is a member of my Form (not necessarily
owned by the form - perhaps a pointer to char or something, not part of
the


I don't understand what you mean by 'a member pointer not owned by a Form'.

Quote:
VCL), when the form's destructor executes then the memory used by the form
is not valid.

correct.

Quote:
Therefore, you cannot access MyPointer, even from outside
the class if it were public , because the Form no longer exists and its
"this" is invalid.
...

wrong. I can: even when 'this'prt is invalid, that memory location is
accessible until freed. Boba




Back to top
JD
Guest





PostPosted: Sat Dec 20, 2003 12:16 pm    Post subject: Re: FormResize() being called after my form's destructor Reply with quote


"Vladimir Stefanovic" <spam (AT) not (DOT) needed> wrote:
Quote:
AFAIK there are no problems with the OnResize event. Please
show both OnResize and the dtor.

Some problem definitely exists!

I tested the OnResize event. It does not get called when the
form is destroyed unless you explicitly do something from
within the dtor to cause it to be called. In that case, the
problem would be with your logic, not the VCL.

~ JD


Back to top
Vladimir Stefanovic
Guest





PostPosted: Sat Dec 20, 2003 4:18 pm    Post subject: Re: FormResize() being called after my form's destructor Reply with quote

Quote:
"Vladimir Stefanovic" <spam (AT) not (DOT) needed> wrote:
AFAIK there are no problems with the OnResize event. Please
show both OnResize and the dtor.

Some problem definitely exists!

I tested the OnResize event. It does not get called when the
form is destroyed unless you explicitly do something from

I tested it too, and couldn't reproduce the problem in the simple
example. I'll try to reduce my code step by step and find what's
the problematic part of the code. I haven't noticed the problem
on my machine, but it crached on some others. Then I included
CodeGuard in the app. build and find invalid pointers access.

I'm not sure what can cause the OnResize after destruction, but
it realy exists. Till then I have to include the aditioonal condition
to avoid that...

Thanks for not forgetting this problem.

Vladimir.




Back to top
Joseph F. Muscarella
Guest





PostPosted: Mon Dec 22, 2003 3:59 pm    Post subject: Re: FormResize() being called after my form's destructor Reply with quote

I Googled the problem, and one thing came up: It appears to have something
to do with the MainMenu when it is destroyed. It apparently causes
OnResize to fire regardless of whether the MainForm has been destroyed. I
haven't tested this, but who knows...

Joe

Quote:
AFAIK there are no problems with the OnResize event. Please
show both OnResize and the dtor.

Some problem definitely exists!

I tested the OnResize event. It does not get called when the
form is destroyed unless you explicitly do something from

I tested it too, and couldn't reproduce the problem in the simple
example. I'll try to reduce my code step by step and find what's
the problematic part of the code. I haven't noticed the problem
on my machine, but it crached on some others. Then I included
CodeGuard in the app. build and find invalid pointers access.

I'm not sure what can cause the OnResize after destruction, but
it realy exists. Till then I have to include the aditioonal condition
to avoid that...

Thanks for not forgetting this problem.

Vladimir.






Back to top
Joseph F. Muscarella
Guest





PostPosted: Mon Dec 22, 2003 4:05 pm    Post subject: Re: FormResize() being called after my form's destructor Reply with quote

Quote:
I don't understand what you mean by 'a member pointer not owned by a
Form'.


I should have been more specific, I guess. A class member that is part of
TForm but is not part of the VCL, so TForm knows nothing of it. It doesn't
own it, so the VCL will not destroy it. My own destructor is responsible
for destroying it.

Quote:
Therefore, you cannot access MyPointer, even from outside
the class if it were public , because the Form no longer exists and its
"this" is invalid.
...

wrong. I can: even when 'this'prt is invalid, that memory location is
accessible until freed. Boba

Not if you try to access it by MainForm->MyPointer

This is dangerous since the memory formerly owned by MainForm **MAY** have
been overwritten and you don't know it. Thus, MyPointer may still be valid
somewhere in the heap (abandoned, and thus a leak) but you can't get to it
through MainForm. Only if you had made a copy of MyPointer *outside* of
MainForm would you still be able to access it (and this would be bad
practice anyway.)

Joe



Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (VCL Components Usage) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.