我在从方法返回对象时调用自动释放的所有时间都会看到示例,但如果在分配内存和返回对象之间发生异常,这不会导致内存泄漏吗?
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读取有问题吗?
答案 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