目标C - 如果在return语句中调用autorelease之前发生异常会发生什么?

时间:2016-09-08 10:02:38

标签: objective-c memory-management

我在从方法返回对象时调用自动释放的所有时间都会看到示例,但如果在分配内存和返回对象之间发生异常,这不会导致内存泄漏吗?

    NSString *newString = [[NSString alloc] init];
    //Do some other stuff which causes exception
    return [newString autorelease];

所以我的意思是要清楚一点:

@autoreleasepool {
    try {
    SomeObject *newObject = [SomeClass generateAutoreleaseObject];
    } @catch (NSException *e) {
        //log exception and carry on.
    }
}

如果generateAutoreleaseObject如下,是否有内存泄漏?

    (SomeObject*)generateAutoreleaseObject {
        SomeObject *newObject = [[SomeObject alloc] init];
        //Do some other stuff which causes exception
        return [newObject autorelease];
    }

如果是这样的话,返回自动释放对象的基础类会处理这个问题,而今晚我可以安全地睡在床上,因为知道stringWithContentsOfURL不会留下任何内存浮动,因为它从URL读取有问题吗?

1 个答案:

答案 0 :(得分:1)

  

但是如果在分配内存和返回对象之间发生异常,这是否会导致内存泄漏?

是的,确实如此。该异常将执行直接从它引发的位置移动到处理程序。这在an example in Apple's Cocoa Exceptions Guide中明确提到:

 - (void)doSomething {
     NSMutableArray *anArray = [[NSMutableArray alloc] initWithCapacity:0];
     [self doSomethingElse:anArray];
     [anArray release];
 }
     

这里的问题显而易见:如果doSomethingElse:方法抛出异常,则会发生内存泄漏。

那么,你怎么能解决这个问题呢?好吧,异常处理语法包括@finally块,该块在@try之后和任何@catch之后运行。

如果-generateAutoreleaseObject中存在异常,您可以使用带有@finally块的本地异常处理程序来确保清理资源,并且如果需要,还可以重新抛出例外。但是请参阅下面有关内部Cocoa代码的信息!

  

如果generateAutoreleaseObject如下,是否有内存泄漏?

是。同样值得注意的是,ARC在这里并不一定有所帮助。再次,控制从投掷到处理点跳转。默认情况下,ARC can't reasonably ensure that it can clean up处于该情况。 (你可以在那个链接看到,你可以使用一个编译器选项。)

  

如果是这样,返回autorelease对象的基础类将处理此

不是真的。如果您的异常跳过涉及它们的堆栈帧,则不保证框架内部的状态。这很难避免,这就是为什么咒语是Cocoa中可恢复错误的例外情况。

有关此主题的两位Apple运行时工程师:Objective-C ARC and longjmp