• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: AU - CW code gen problems - solved!
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: AU - CW code gen problems - solved!


  • Subject: Re: AU - CW code gen problems - solved!
  • From: Philippe Wicker <email@hidden>
  • Date: Sat, 29 Mar 2003 10:34:58 +0100

On Saturday, March 29, 2003, at 09:43 AM, Marc Poirier wrote:

Hi Marc,

Mea Culpa. Your bug was actually my bug. The modification to the SDK I posted some times ago to make the sources compatible with CW was incorrect. The modification you suggest is the good one. Note that the code for CW will also work for PB/gcc.

I can try to explain the problem. This is due to the "confusion" made in C between a pointer and an array.

If you declare an array variable, eg:

EventHandlerRef theHandlers[12] ;

and if you pass this variable to a function, it degenerates to a EventHandlerRef * type. When you apply the & operator to the variable theHandlers, you get the address of the variable theHandlers ie the address of the array. That's why you will obtain the same result if you execute:

printf ("theHandlers 0x%x", theHandlers) ;

or:

printf ("theHandlers 0x%x", &theHandlers) ;

Now if you declare a pointer variable, eg:

EventHandlerRef * theHandlers ;

then passing theHandlers to a function does not degenerates its type. This means that theHandlers will be the value of the pointer, and & theHandlers will be the **address** of the pointer theHandlers. Not exactly the same.

This little piece of code

int main (int argc, char* argv[])
{
EventHandlerRef theHandlers[12] ;
printf("theHandlers 0x%x, &theHandlers 0x%x\n", theHandlers, &theHandlers) ;

EventHandlerRef* theHandlers_ = new EventHandlerRef[12] ;
printf("theHandlers_ 0x%x, &theHandlers_ 0x%x\n", theHandlers_, &theHandlers_) ;
}

compiled with CW gives the output:

theHandlers 0xbffffc98, &theHandlers 0xbffffc98
theHandlers_ 0x54ff0, &theHandlers 0xbffffc90

Sorry for the error I made.

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.



Philippe Wicker
email@hidden
_______________________________________________
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.

  • Follow-Ups:
    • Re: AU - CW code gen problems - solved!
      • From: Brian Willoughby <email@hidden>
    • Re: AU - CW code gen problems - solved!
      • From: Bill Stewart <email@hidden>
    • Re: AU - CW code gen problems - solved!
      • From: Marc Poirier <email@hidden>
  • Prev by Date: Core Audio replacement for ASIO Positioning Protocol
  • Next by Date: Re: OT: OS X documentation
  • Previous by thread: Re: AU - CW code gen problems - solved!
  • Next by thread: Re: AU - CW code gen problems - solved!
  • Index(es):
    • Date
    • Thread