Re: blocks and autorelease weirdness
Re: blocks and autorelease weirdness
- Subject: Re: blocks and autorelease weirdness
- From: Ken Ferry <email@hidden>
- Date: Mon, 19 Apr 2010 03:49:48 -0700
On Mon, Apr 19, 2010 at 3:09 AM, Henk Kampman
<email@hidden>wrote:
>
> On 19 apr 2010, at 11:41, Jean-Daniel Dupas wrote:
>
> >
> >
> > Le 19 avr. 2010 à 11:35, Henk Kampman a écrit :
> >
> >> Have a look at the following code
> >>
> >> -(void) test
> >> {
> >> testString = NULL;
> >>
> >> dispatch_async(dispatch_get_global_queue(0, 0), ^{
> >> dispatch_async(dispatch_get_main_queue(), ^{
> >>
> >> NSString* aString = [[NSMutableString alloc] init];
> >> NSLog(@"retainCount: %d",[aString retainCount]);
> >>
> >> testString = [aString retain];
> >>
> >> [aString release];
> >>
> >> dispatch_async(dispatch_get_main_queue(), ^{
> >> NSLog(@"retainCount: %d",[testString
> retainCount]);
> >> });
> >> });
> >> });
> >> }
> >>
> >> As expected the output is:
> >>
> >> retainCount: 1
> >> retainCount: 1
> >>
> >> However when I change [aString release] to [aString autorelease] the
> output shows:
> >>
> >> retainCount: 1
> >> retainCount: 2
> >>
> >> Why?
> >>
> >> BTW I first noticed this behavior when my application started leaking
> the QTMovie objects I was creating in a block.
> >>
> >> -
> >
> > Because you should never expect something from retainCount.
> > See archives for details.
>
> Are you sure? I'm not using GC and everything executes within the main
> thread.
>
> In this case the retainCount clearly reflects what I'm seeing in my code!
>
> But lets assume you're correct, it still doesn't explain the memory leak
> when I use autorelease instead of release.
>
Yes, you found something real.
When you use dispatch_async to the global concurrent queue, you are not
executing on the main thread. Normally in such a situation you need to
create an autorelease pool if you're going to use Cocoa.
It turns out that dispatch creates an autorelease pool of last resort, but
it's not cleared very often, and relying on it is not encouraged. Dispatch
doesn't want to take the overhead of creating and destroying autorelease
pools every time when some low level systems are not using Objective-C. If
you work at the NSOperation level, this is handled.
You can clean the memory up more quickly by wrapping your code in an
autorelease pool.
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// your code
[pool drain];
});
-Ken
Cocoa Frameworks
>
> - Henk
>
> >
> > -- Jean-Daniel
> >
> >
> >
> >
>
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
>
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden