Re: occasional crash in AudioQueueStop()
Re: occasional crash in AudioQueueStop()
- Subject: Re: occasional crash in AudioQueueStop()
- From: Christopher Liscio <email@hidden>
- Date: Fri, 17 Oct 2008 21:01:33 -0400
Brian,
I appreciate your experience in the matter, though my 'bad advice from
the internet' was supplied by Apple:
http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Concepts/ObjectOwnership.html#/
/apple_ref/doc/uid/20000043-1044135
...this advice has also been backed up by many of my respected
developer friends who've collectively been working with Cocoa for many
decades.
I do agree that there's probably some other fundamental problem that's
causing this specific behavior, and I'll have to consider a different
approach like you describe (with a retain/release outside the callback).
However, I won't be changing all my other (non-audio-interacting)
objects to behave differently from what Apple prescribes for dealing
with delegates.
Cheers,
Chris Liscio
http://SuperMegaUltraGroovy.com
Acoustic measurement software for Mac OS X -- http://www.FuzzMeasure.com
On Oct 17, 2008, at 6:29 PM, Brian Willoughby wrote:
Chris, it seems that you're a victim of bad advice from the
internet. What you are calling "common practice" is a bad
practice. I Googled 'retain delegate' and found some really bad
code. It seems that newcomers to Cocoa are learning bad habits and
then spreading these around. I have been writing and releasing
Cocoa code since 1991, and I have never found a reason to violate
the rule that all object references should be retained or set to
nil. The fact that an object reference happens to be a delegate
object is no reason to ignore this rule.
To put it in perspective, your callback is sending a message to a
delegate object which disappears unpredictably. That shows a
fundamental problem. Your reluctance to retain the delegate object
for the duration of time that your callback is in place, citing
retain loops as an excuse, shows that there is a design flaw in your
object graph as well. But it's your code, and you can hack it up
however you please.
My point is that not every program design will suffer from the
object graph cycle problems that your code has. Therefore,
recommending retain and release calls inside a callback is not good
general advice. I realize that you're reciting advice that you've
read elsewhere, but it's bad advice that you received nonetheless.
One very important problem with your design is that you should avoid
allocating or freeing memory inside a callback. While retain does
not allocate memory, release can easily free memory. Moving retain/
release outside the callback register/deregister solves this issue,
and also makes your callback have lower overhead.
The best advice is to retain the delegate object before you register
any callback which uses that delegate object, and then release the
delegate afterwards. There are many ways to organize your code to
achieve this goal, and if you end up with a retain cycle then you
should look elsewhere for a fix.
Brian Willoughby
Sound Consulting
On Oct 17, 2008, at 13:08, Christopher Liscio wrote:
I'm not sure that's the best solution, Brian.
In the case you suggest, it would work provided the releasing of the
delegate (and the teardown of the callback) is done outside of the
dealloc call.
In my case, the delegate of the audio queue object in question owns
a reference to the audio queue object, and this retain strategy you
suggest would result in a retain cycle, since I tear down the
callback in the dealloc call (as most likely would).
It's common practice to not retain a delegate to avoid retain cycles
like this, and I try to stick to that as a general rule of thumb in
my code.
The retain 'fix' I proposed isn't meant to be slapped onto every
call to a delegate--only the calls made within CoreAudio callbacks
that can be invoked outside the main run loop.
Chris Liscio
http://SuperMegaUltraGroovy.com
Acoustic measurement software for Mac OS X -- http://www.FuzzMeasure.com
On Oct 17, 2008, at 3:09 PM, Brian Willoughby wrote:
The suggested retain/release is the right solution in the wrong
place. You don't want to surround every single delegate call with
a retain and release. Instead, you want to call retain before you
set up your callback, to make sure that your delegate object lives
as long as your callback. Then, if you ever tear down your
callback (which is pretty unlikely if the callback lives for the
duration of your program), you should call release after the
callback has been successfully removed.
There are ways to make this a little easier by altering the way you
allocate and initialize your delegate object, but I won't get into
that here. Basically, I just wanted to touch on enough Cocoa to
get folks sorted for their CoreAudio callbacks.
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden