• 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: Understanding ARC
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Understanding ARC


  • Subject: Re: Understanding ARC
  • From: Charles Srstka <email@hidden>
  • Date: Sun, 25 May 2014 01:34:16 -0500

On May 24, 2014, at 5:04 PM, Jens Alfke <email@hidden> wrote:

> On May 24, 2014, at 2:34 PM, Jamie Ojomoh <email@hidden> wrote:
>
>> In the example, everything inside the autoreleasepool block will be
>> released as soon as the block ends, so it's necessary to declare the return
>> value outside the block.
>
> No, in general ARC understands that the return value needs to keep a reference, so it’s safe to put the return statement inside the autorelease block. In your specific example, returnString was allocated before you created your autorelease pool, so that pool won’t release it anyway. Also, you allocated returnString using an alloc/init sequence so it’s not in an autorelease pool at all.

This isn't strictly true; when you are returning objects by reference, doing so inside the @autoreleasepool will cause a crash. For example:

#import <Foundation/Foundation.h>

static BOOL DoSomethingElse(NSError *__autoreleasing *error) {
    if (error) *error = [[NSError alloc] initWithDomain:@"Foo" code:-1 userInfo:nil];

    return NO;
}

static BOOL DoSomething(NSError *__autoreleasing *error) {
    @autoreleasepool {
        return DoSomethingElse(error);
    }
}

int main(int argc, const char * argv[]){
    @autoreleasepool {
        NSError *error = nil;

        if (DoSomething(&error)) {
            NSLog(@"Success");
        } else {
            NSLog(@"Error: %@", error); // crashes here
        }
    }
    return 0;
}

Interestingly, this still happens even if you declare the NSError variable out of the @autoreleasepool block:

#import <Foundation/Foundation.h>

static BOOL DoSomethingElse(NSError *__autoreleasing *error) {
    if (error) *error = [[NSError alloc] initWithDomain:@"Foo" code:-1 userInfo:nil];

    return NO;
}

static BOOL DoSomething(NSError *__autoreleasing *error) {
    NSError *theError = nil;

    @autoreleasepool {
        if (DoSomethingElse(&theError)) {
            return YES;
        } else {
            if (error) *error = theError;
            return NO;
        }
    }
}

int main(int argc, const char * argv[]){
    @autoreleasepool {
        NSError *error = nil;

        if (DoSomething(&error)) {
            NSLog(@"Success");
        } else {
            NSLog(@"Error: %@", error); // still crashes here
        }
    }
    return 0;
}

The only thing that avoids the crash is returning outside of the @autoreleasepool block:

#import <Foundation/Foundation.h>

static BOOL DoSomethingElse(NSError *__autoreleasing *error) {
    if (error) *error = [[NSError alloc] initWithDomain:@"Foo" code:-1 userInfo:nil];

    return NO;
}

static BOOL DoSomething(NSError *__autoreleasing *error) {
    BOOL success;
    NSError *theError = nil;

    @autoreleasepool {
        success = DoSomethingElse(&theError);
    }

    if (success) {
        return YES;
    } else {
        if (error) *error = theError;
        return NO;
    }
}

int main(int argc, const char * argv[]){
    @autoreleasepool {
        NSError *error = nil;

        if (DoSomething(&error)) {
            NSLog(@"Success");
        } else {
            NSLog(@"Error: %@", error); // now this actually works
        }
    }
    return 0;
}

The thing that makes this really insidious is that you only get the crash when an error occurs, so if you have an error case that only happens a tiny percentage of the time, it can slip through your testing.

Charles
_______________________________________________

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


References: 
 >Understanding ARC (From: Jamie Ojomoh <email@hidden>)

  • Prev by Date: Re: string literals and performance
  • Next by Date: Re: string literals and performance
  • Previous by thread: Re: Understanding ARC
  • Next by thread: Re: Understanding ARC
  • Index(es):
    • Date
    • Thread