On Mon, Apr 27, 2009 at 3:17 PM, Symphonik <[email protected]> wrote:
> All,
>
> I am using a couple of methods that use NSError ** pointers to communicate
> error conditions. These methods run on background threads and so have their
> own autorelease pools set up. I pass an NSError pointer down a couple of
> method calls -- by the time it comes back up, it has been dealloc'd by the
> autorelease pool. A simple example (this will run if you want to try it for
> yourself):
>
> - (void)applicationDidFinishLaunching:(UIApplication *)application {
>    [self performSelectorInBackground:@selector(runBackgroundProcess)
> withObject:nil];
> }
>
> - (void)runBackgroundProcess {
>    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
>
>    NSError *error = nil;
>    [self runSomethingThatWillFail:&error];
>
>     if(error) {
>        NSLog(@"error: %@", error);  // <==== CRASH HERE, EXC_BAD_ACCESS due
> to bogus pointer
>     }
>
>     [pool release];
> }
>
> - (void)runSomethingThatWillFail:(NSError **)error {
>    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
>    NSArray *directoryContents = [[NSFileManager defaultManager]
> contentsOfDirectoryAtPath:@"/BOGUS" error:error];
>    [pool release];
> }
>
> So I crash in runBackgroundProcess since the error is getting wiped by the
> local autorelease pool. Okay, so I'll retain it...
>
> - (void)runSomethingThatWillFail:(NSError **)error {
>    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
>    NSArray *directoryContents = [[NSFileManager defaultManager]
> contentsOfDirectoryAtPath:@"/BOGUS" error:error];
>    [*error retain];
>    [pool release];
> }
>
> Well, now I have a leak of that NSError object... so I should autorelease
> it, I suppose. But that autorelease needs to be outside the release of the
> local pool, so it becomes:
>
> - (void)runSomethingThatWillFail:(NSError **)error {
>    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
>    NSArray *directoryContents = [[NSFileManager defaultManager]
> contentsOfDirectoryAtPath:@"/BOGUS" error:error];
>    [*error retain];
>    [pool release];
>    [*error autorelease];
> }
>
> Now it works and isn't leaking anymore. But factor in that I have to do some
> checking on the existence of the error before I dereference it, etc... this
> is becoming some ugly code just to get my NSError back up the chain.
>
> Am I overthinking this? Anyone else have better suggestions?

Why does -runSomethingThatWillFail: have its own pool? You already
have a pool, you don't need a second one. Get rid of that pool and
suddenly everything becomes easy.

If it really *must* have a pool for some reason, then the
retain/autorelease dance is the standard procedure for getting
returned objects out of the current pool and into the next one. Think
of that error value as a return value, even though it's returned by
reference and not by value.

Mike
_______________________________________________

Cocoa-dev mailing list ([email protected])

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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to