 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Marcelo R. Lopez, Jr. Guest
|
Posted: Tue Jun 15, 2004 10:37 pm Post subject: double destruction of ActiveForm.... |
|
|
This has been working for almost two years, and suddenly it's not working
anymore....
I have a set of ActiveLibraries with ActiveForms inside them that I
instrument into my application by instantiating them via
CoClassFactory::CreateInstance()...and then inject inside of panels of the
main app ( encapsulating by a TOleContainer ).
Just before handling the exit of the application I perform an orderly
shutdown of each of these ActiveLibraries.
The problem is that now, after almost two years of working just fine. I will
get a circumstance, where ONE of these ActiveLibraries will get it's
ActiveForms destructor called more than once. It only happens to this one
ActiveForm within one of the ActiveLibraries.
I've tried Memproof, but that doesn't show me enough granularity. There used
to be SleuthQA, but they're gone now. I've tried the AutomatedQA, but the
Demo only does so much.
Has any one ever run across a situation where ATL has gotten it's reference
counts screwy, and tried to forceably destruct an ActiveForm needlessly (
Notice, it's not calling the release for the ActiveLibrary either ), it's
calling the ~TActiveForm base class for my form. What's oddest in all of
this...is that I NEVER get my "ActiveFormDestroy" event handler called, even
though I've got code in there to watchdog it and do some
"OutputDebugString()" calls.
Any ideas, no matter how hair-brained, will be greatly appreciated.
Marcelo R. Lopez, Jr.
Todays's quote of the day:
Don't EVER try to do COM by hand, it's like when your mother told you not to
touch a burner on a stovetop. But you touched it anyway.
|
|
| Back to top |
|
 |
Marcelo R. Lopez, Jr. Guest
|
Posted: Fri Jun 18, 2004 3:59 pm Post subject: Re: double destruction of ActiveForm.... |
|
|
No one has any ideas ??
"Marcelo R. Lopez, Jr." <mlopez (AT) voicerite (DOT) com> wrote
| Quote: | This has been working for almost two years, and suddenly it's not working
anymore....
I have a set of ActiveLibraries with ActiveForms inside them that I
instrument into my application by instantiating them via
CoClassFactory::CreateInstance()...and then inject inside of panels of the
main app ( encapsulating by a TOleContainer ).
Just before handling the exit of the application I perform an orderly
shutdown of each of these ActiveLibraries.
The problem is that now, after almost two years of working just fine. I
will
get a circumstance, where ONE of these ActiveLibraries will get it's
ActiveForms destructor called more than once. It only happens to this one
ActiveForm within one of the ActiveLibraries.
I've tried Memproof, but that doesn't show me enough granularity. There
used
to be SleuthQA, but they're gone now. I've tried the AutomatedQA, but the
Demo only does so much.
Has any one ever run across a situation where ATL has gotten it's
reference
counts screwy, and tried to forceably destruct an ActiveForm needlessly (
Notice, it's not calling the release for the ActiveLibrary either ), it's
calling the ~TActiveForm base class for my form. What's oddest in all of
this...is that I NEVER get my "ActiveFormDestroy" event handler called,
even
though I've got code in there to watchdog it and do some
"OutputDebugString()" calls.
Any ideas, no matter how hair-brained, will be greatly appreciated.
Marcelo R. Lopez, Jr.
Todays's quote of the day:
Don't EVER try to do COM by hand, it's like when your mother told you not
to
touch a burner on a stovetop. But you touched it anyway.
|
|
|
| Back to top |
|
 |
Jean-Marie Babet Guest
|
Posted: Fri Jun 18, 2004 7:44 pm Post subject: Re: double destruction of ActiveForm.... |
|
|
Hello Marcelo,
If the destructor of a particular instance of an object is being invoked
more than once, specially an instance of ActiveForm, which is not something
that one typically creates many instances of, I would suspect two culprits:
1. Memory corruption
2. Bad codegen
The second item is easier to track down. Put plainly, the compiler messed up
and generated code that results in two calls to the destructor. To track
this down, I would try to find out who's calling the destructor. One
approach would be to hardcode a breakpoint in the destructor and use a
debugger. [You can do that by having call to 'DebugBreak' or, as in the old
days, hardcode the emission of the __emit__(0xcc) ]. The other approach
would be to generate assembly and find references to the destructor. Things
get a little complex with the latter because undoubtedly this destructor
will be virtual, which means the reference to it will probably be in a
vtable - so it won't be clear who's directly calling this method.
Have stack trace from the hardcoded breakpoint might prove useful, specially
if you end up with two different stack traces. If you need help looking at
these, I'll be more than happy to help out and have others here [who are
more CPU window savvy] take a peek also.
The first item is harder to track down. In the past I've used tools [some of
which you mentioned], I've reordered the order of object modules and
libraries - this does not fix the problem, but sometimes it moves the issue
to some other places that may be easier to spot. Or the very fact that the
issue moves somewhere else is often a good hint that we're after a memory
corruption.
On the issue of memory corruption, often switching from debug to non-debug
builds [or vice-versa] will change things also.
I apologize for not providing very concrete steps but this type of problem
is elusive and often requires broad trials before you can narrow down. I can
confirm that I have had plenty of double destructor calls and they often
take a long time to resolve.
Regards,
Bruneau.
"Marcelo R. Lopez, Jr." <mlopez (AT) voicerite (DOT) com> wrote
| Quote: | No one has any ideas ??
"Marcelo R. Lopez, Jr." <mlopez (AT) voicerite (DOT) com> wrote in message
news:40cf7a13$1 (AT) newsgroups (DOT) borland.com...
This has been working for almost two years, and suddenly it's not
working
anymore....
I have a set of ActiveLibraries with ActiveForms inside them that I
instrument into my application by instantiating them via
CoClassFactory::CreateInstance()...and then inject inside of panels of
the
main app ( encapsulating by a TOleContainer ).
Just before handling the exit of the application I perform an orderly
shutdown of each of these ActiveLibraries.
The problem is that now, after almost two years of working just fine. I
will
get a circumstance, where ONE of these ActiveLibraries will get it's
ActiveForms destructor called more than once. It only happens to this
one
ActiveForm within one of the ActiveLibraries.
I've tried Memproof, but that doesn't show me enough granularity. There
used
to be SleuthQA, but they're gone now. I've tried the AutomatedQA, but
the
Demo only does so much.
Has any one ever run across a situation where ATL has gotten it's
reference
counts screwy, and tried to forceably destruct an ActiveForm needlessly
(
Notice, it's not calling the release for the ActiveLibrary either ),
it's
calling the ~TActiveForm base class for my form. What's oddest in all of
this...is that I NEVER get my "ActiveFormDestroy" event handler called,
even
though I've got code in there to watchdog it and do some
"OutputDebugString()" calls.
Any ideas, no matter how hair-brained, will be greatly appreciated.
Marcelo R. Lopez, Jr.
Todays's quote of the day:
Don't EVER try to do COM by hand, it's like when your mother told you
not
to
touch a burner on a stovetop. But you touched it anyway.
|
|
|
| Back to top |
|
 |
Marcelo R. Lopez, Jr. Guest
|
Posted: Tue Jun 22, 2004 4:08 pm Post subject: Re: double destruction of ActiveForm.... |
|
|
Jean-Marie,
My thoughts exactly...but here's what I discovered. Inside my active
form, I have a button ...a TButton, which I set up in the designer as
being "Enabled = False, Visible = False". If I start up my application,
and let it run, I receive certain notifications which I process, and add
to a TreeView, sounds simple so far, right ?
Well, while I'm processing these notifications, if I receive a
notification of a certain type, I would set the Visible and Enabled
properties of this particular TButton to "True". Well, not only does the
control NOT get displayed, but when I exit, that's when I get this
double-destructor call sequence. I discovered this by
good-old-fashioned, break and step. I kept putting breaks further and
further down the processing chain until I got to this piece of code that
handled "turning the button On or Off".
If I handled the notification in question, fully, with exception of
updating this Button's state, everything was fine. If I let it perform
the Enabled = true; Visible = true; then I would run into problems.
Deleting the button, and creating a different button, didn't make a
difference. I tried so many different combinations it wasn't even funny
! If the button is disabled and invisible to start with, it wouldn't
display, and it would generate this behavior. Another thing I noticed,
and it might be along the lines of your bad code-gen theory is that that
button is the ONLY button that has those two properties set that give me
the problem. I have other buttons that are conditionally shown/enabled
during similar circumstances, and none of those buttons ( or code
surrounding them ) have given me such problems. How can I tell what the
known issues with generating resources exist within BCB ? I looked in
Quality Central and didn't see anything that would remotely indicate a
problem with handling resource creation/destruction.
I continue my research.......
Marcelo
Jean-Marie Babet wrote:
| Quote: | Hello Marcelo,
If the destructor of a particular instance of an object is being invoked
more than once, specially an instance of ActiveForm, which is not something
that one typically creates many instances of, I would suspect two culprits:
1. Memory corruption
2. Bad codegen
The second item is easier to track down. Put plainly, the compiler messed up
and generated code that results in two calls to the destructor. To track
this down, I would try to find out who's calling the destructor. One
approach would be to hardcode a breakpoint in the destructor and use a
debugger. [You can do that by having call to 'DebugBreak' or, as in the old
days, hardcode the emission of the __emit__(0xcc) ]. The other approach
would be to generate assembly and find references to the destructor. Things
get a little complex with the latter because undoubtedly this destructor
will be virtual, which means the reference to it will probably be in a
vtable - so it won't be clear who's directly calling this method.
Have stack trace from the hardcoded breakpoint might prove useful, specially
if you end up with two different stack traces. If you need help looking at
these, I'll be more than happy to help out and have others here [who are
more CPU window savvy] take a peek also.
The first item is harder to track down. In the past I've used tools [some of
which you mentioned], I've reordered the order of object modules and
libraries - this does not fix the problem, but sometimes it moves the issue
to some other places that may be easier to spot. Or the very fact that the
issue moves somewhere else is often a good hint that we're after a memory
corruption.
On the issue of memory corruption, often switching from debug to non-debug
builds [or vice-versa] will change things also.
I apologize for not providing very concrete steps but this type of problem
is elusive and often requires broad trials before you can narrow down. I can
confirm that I have had plenty of double destructor calls and they often
take a long time to resolve.
Regards,
Bruneau.
"Marcelo R. Lopez, Jr." <mlopez (AT) voicerite (DOT) com> wrote in message
news:40d31144$1 (AT) newsgroups (DOT) borland.com...
No one has any ideas ??
"Marcelo R. Lopez, Jr." <mlopez (AT) voicerite (DOT) com> wrote in message
news:40cf7a13$1 (AT) newsgroups (DOT) borland.com...
This has been working for almost two years, and suddenly it's not
working
anymore....
I have a set of ActiveLibraries with ActiveForms inside them that I
instrument into my application by instantiating them via
CoClassFactory::CreateInstance()...and then inject inside of panels of
the
main app ( encapsulating by a TOleContainer ).
Just before handling the exit of the application I perform an orderly
shutdown of each of these ActiveLibraries.
The problem is that now, after almost two years of working just fine. I
will
get a circumstance, where ONE of these ActiveLibraries will get it's
ActiveForms destructor called more than once. It only happens to this
one
ActiveForm within one of the ActiveLibraries.
I've tried Memproof, but that doesn't show me enough granularity. There
used
to be SleuthQA, but they're gone now. I've tried the AutomatedQA, but
the
Demo only does so much.
Has any one ever run across a situation where ATL has gotten it's
reference
counts screwy, and tried to forceably destruct an ActiveForm needlessly
(
Notice, it's not calling the release for the ActiveLibrary either ),
it's
calling the ~TActiveForm base class for my form. What's oddest in all of
this...is that I NEVER get my "ActiveFormDestroy" event handler called,
even
though I've got code in there to watchdog it and do some
"OutputDebugString()" calls.
Any ideas, no matter how hair-brained, will be greatly appreciated.
Marcelo R. Lopez, Jr.
Todays's quote of the day:
Don't EVER try to do COM by hand, it's like when your mother told you
not
to
touch a burner on a stovetop. But you touched it anyway.
|
|
|
| Back to top |
|
 |
Marcelo R. Lopez, Jr. Guest
|
Posted: Thu Jun 24, 2004 8:20 pm Post subject: Re: double destruction of ActiveForm.... |
|
|
Ok...so here's the scoop...and I think there's definitely some funky
code-gen going on .
The long and the short of it is as follows:
If I set the "Visible" flag of a particular TButton to False in the
designer, and later in my application
try to set it's Visible flag to True.....I get this crash on exit.
If I set it the Visible flag to True in the designer, and later set it's
Visible flag to False ( I was setting it to false in an initialization
interface defined in the Impl object that calls a public method in the
active form to set the property to false ), I get the crash on exit. I
know that the ActiveForm has already gone through it's creation at this
point, because I implemented ActiveFormCreate and stuck a
OutputDebugString(), just to see that it had already been passed through.
If I set the Visible flag to false, and then in the same initialization
interface in the Impl object do the following:
#define WM_MY_DISABLE_XXX WM_USER+1023
TGuiFormImpl::Intiailize(.....)
{
// Other initialization....
::PostMessage( form->Handle, WM_MY_DISABLE_XXX, 0,0 );
}
and implement WndProc for the Activeform:
void __fastcall TGUIForm::WndProc(Messages::TMessage &Message)
{
switch ( Message.Msg ){
case WM_MY_DISABLE_XXX:
{
ButtonCallBack->Enabled = false;
ButtonCallBack->Visible = false;
}
break;
default:
TActiveForm::WndProc(Message);
break;
}
}
THIS, actually works. I can then enable/disable, hide/show the button at
WILL.
Very strange.....as an FYI for anyone who ever runs into a weird
behavior like this. It was VERY tricky to track down. Thanks for your
help Jean-Marie. This is all on BCB6 + Update 4, in case
anyone's curious.
Marcelo
|
|
| Back to top |
|
 |
Jean-Marie Babet Guest
|
Posted: Thu Jun 24, 2004 10:32 pm Post subject: Re: double destruction of ActiveForm.... |
|
|
Marcelo,
Thanks for the follow-up post.
| Quote: | ( I was setting it to false in an initialization
interface defined in the Impl object that calls a public method in the
active form to set the property to false )
|
This is probably not related but due to the Delphi nature of the underlying
objects used by CBuilder sometimes there are timing issues at creation and
destruction time. As long as this initialization interface is not called too
early, I don't think this is the problem. Too early would be, for example,
if the initialization interface is called from a virtual method invoked by
the underlying VCL object. You've probably seen posts here also recommending
that the constructor be used instead of the Create-related events/virtuals
typically invoked by VCL.
| Quote: | If I set the Visible flag to false, and then in the same initialization
interface in the Impl object do the following:
....
THIS, actually works. I can then enable/disable, hide/show the button at
WILL.
|
This definitely points to a timing issue. I'm curious what the stack trace
looked like in the previous setup.
But again, thanks for the post and happy to hear to have a resolution.
Regards,
Bruneau.
|
|
| Back to top |
|
 |
|
|
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
|
|