Re: AU - CW code gen problems - solved!
Re: AU - CW code gen problems - solved!
- Subject: Re: AU - CW code gen problems - solved!
- From: Marc Poirier <email@hidden>
- Date: Sat, 29 Mar 2003 09:43:50 +0100 (CET)
Alright, I found the bug. It was not as complex as I thought it was,
actually. And for some reason I felt motivated to try to search for it
some more at 2 am on this Friday night, hmmm...
In CarbonEventHandler.cpp, this is no good:
CarbonEventHandler::~CarbonEventHandler()
{
if (mHandlers != NULL) {
int count = CFDictionaryGetCount(mHandlers);
EventHandlerRef theHandlers[count];
CFDictionaryGetKeysAndValues(mHandlers, NULL, (const void **) &theHandlers);
for (int i = 0; i < count; i++)
RemoveEventHandler(theHandlers[i]);
CFDictionaryRemoveAllValues(mHandlers);
CFRelease (mHandlers);
}
}
This line:
CFDictionaryGetKeysAndValues(mHandlers, NULL, (const void **) &theHandlers);
should be changed to:
CFDictionaryGetKeysAndValues(mHandlers, NULL, (const void **) theHandlers);
Now the funny thing about that is that, with gcc, that doesn't matter.
theHandlers and &theHandlers are equal. I'm not going to try and act like
I understand why, because I don't (maybe this is just a
the-way-C-works-at-a-low-level thing that I'm not educated on), but with
CW it does matter. Well, there's more to it than that. The thing is that
CW does not allow the declaration of theHandlers as it is:
EventHandlerRef theHandlers[count];
I guess because EventHandlerRef is a pointer to an opaque struct type, CW
doesn't like that sort of default creation. So I had to modify the
function like so in order to build with CW:
CarbonEventHandler::~CarbonEventHandler()
{
if (mHandlers != NULL) {
int count = CFDictionaryGetCount(mHandlers);
#ifdef __MWERKS__
EventHandlerRef *theHandlers = (EventHandlerRef*) malloc(count * sizeof(EventHandlerRef));
#else
EventHandlerRef theHandlers[count];
#endif
CFDictionaryGetKeysAndValues(mHandlers, NULL, (const void **) theHandlers);
for (int i = 0; i < count; i++)
RemoveEventHandler(theHandlers[i]);
CFDictionaryRemoveAllValues(mHandlers);
CFRelease (mHandlers);
#ifdef __MWERKS__
free(theHandlers);
#endif
}
}
When I malloc the array theHandlers at runtime like that, then theHandlers
and &theHandlers are NOT equal, and then it makes a big difference that
CFDictionaryGetKeysAndValues gets passed the correct not-referenced
argument theHandlers.
Why was this causing a crash? Because RemoveEventHandler was getting
bogus arguments passed and therefore not succeeding in removing the event
handlers. Then, after the CarbonEventHandler parent class was destroyed,
TheEventHandler would receive a kEventWindowClose event. TheEventHandler
tries to pass it off to the CarbonEventHandler instance (which is now
destroyed) HandleEvent and then the crash occurs.
So anyway, the moral of the story is that this:
CFDictionaryGetKeysAndValues(mHandlers, NULL, (const void **) &theHandlers);
should be:
CFDictionaryGetKeysAndValues(mHandlers, NULL, (const void **) theHandlers);
However, aside from this bug, I also have some new issues to bring up as a
result of this bug fixing quest.
First of all, why is the kEventWindowClose event being received after the
AUCarbonView is destroyed?
Also, maybe there should be error checking performed for
RemoveEventHandler? As a matter of fact, if you start catching the
results of RemoveEventHandler, you'll see that it fails every time except
for removing kEventWindowClose's event handler (at least that one doesn't
fail, as we've learned, it's the most important one). I'm way too sleepy
to try to start delving into that issue, but I guess maybe it has
something to do with them all being kEventClassControl event handlers for
controls that have been destroyed at that point, maybe... Anyway, the
point is almost every attempt at RemoveEventHandler fails with paramErr.
Marc
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.