Objective c 我应该在@finally子句中加入[池漏]吗?

Objective c 我应该在@finally子句中加入[池漏]吗?,objective-c,cocoa,Objective C,Cocoa,经过多年的Java开发,我开始使用Objective-C编程。我有点纠结的一个问题是内存管理。特别是,书中和网上的大多数例子似乎都没有考虑到异常导致的内存泄漏。例如,考虑以下方法: -(void) doSomething { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; // Allocate some autoreleased objects here NSString *data =

经过多年的Java开发,我开始使用Objective-C编程。我有点纠结的一个问题是内存管理。特别是,书中和网上的大多数例子似乎都没有考虑到异常导致的内存泄漏。例如,考虑以下方法:

-(void) doSomething  
{  
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];

    // Allocate some autoreleased objects here

    NSString *data = [NSString stringWithString@"Hello"];

    // Do some work, exception could be thrown

    [PotentialExeptionThrower maybeThrowException];

    // Clean up autorelease objects

    [pool drain];
}
上述内容是否应该按如下方式重写以防止任何潜在的内存泄漏

-(void) doSomething  
{  
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];

     @try {

        // Allocate some autoreleased objects here

        NSString *data = [NSString stringWithString@"Hello"];

        // Do some work, exception could be thrown

        [PotentialExeptionThrower maybeThrowException];

    } @finally {
        // Clean up autorelease objects

        [pool drain];
    }
}
上面的代码是否因为@try-@catch而效率较低

谢谢

这在中进行了解释。你不必那么做。关键是,如果下部水池排水,则未排水的上部水池也会自动排水。因此,是的,自动释放对象的释放会因异常而延迟,但它们最终会被释放

可以这样说明:

NSAutoreleasePool* A = [[NSAutoreleasePool alloc] init];
NSAutoreleasePool* B = [[NSAutoreleasePool alloc] init];

    .... do many things. Put things in B ...

NSAutoreleasePool* C = [[NSAutoreleasePool alloc] init];

    .... do many things. Put things in C ...

[A drain]; // it automatically drains B and C, too!

请注意,您不必经常设置游泳池。在每一种方法中都设置它肯定是一种过分的做法。通常情况下,您不会开始添加本地池,除非通过仪器进行的实际测量表明一个方法中保存了太多的自动释放对象。

自动释放池是特殊的–正常的“如果您新建/分配/复制,您必须释放”并不完全适用。创建自动释放池时,会将其放置在特殊堆栈上。如果您忽略了排放一个池,那么如果在堆栈中之前的任何池都被排放,那么它将被排放。不需要在catch块中进行排水,但异常可能会延迟池排水。阅读“”了解详细信息。

一般来说:不,你不应该。在异常路径上根本不应排空池。相反,当其父池关闭时,它将自动排空。(如果调用层次结构更上层的代码试图检查异常,那么按您的方式执行将导致崩溃,因为您的finally子句将释放异常。)


例外情况是当您负责最外层的池时,这很可能发生在多线程代码中。在这种情况下,如果希望代码生成异常,则必须捕获异常并将其挤压或处理,然后排空自动释放池。(不这样做会导致崩溃。如果您自己不引发任何异常,这实际上是可以接受的,因为系统框架引发的任何异常都表明存在编程错误,并使您的程序处于未定义状态。)

请注意,Mac OS X和iOS应用程序中的异常通常只保留用于指示不可恢复、程序员错误

如果通过框架抛出异常,行为未定义

例外情况不得用于流量控制


(正如其他人所说——在异常情况下不要释放池。父池将清理它。)

不,您不应该这样做。我知道您的经验受到多年Java的影响,您需要改变处理异常的方式

顾名思义,例外并不是Cocoa应用程序中正常程序流程的一部分。异常用于捕获开发人员您所犯的错误,在您的应用程序发布之前,应先处理。用单元测试覆盖您的数据模型,找出其中的每一个

例如,
NSInvalidArgumentException
是不应该潜入生产代码的。通过单元测试验证用户输入并覆盖逻辑的边缘案例

对于不是您的错误,并且您可以从中恢复的错误,您应该改为使用
NSError
实例。它们具有适合最终用户的本地化描述的良好特性<代码>n错误还具有处理适当恢复选项的功能,如“取消”或“重试”


我在这里就iOS上的异常和错误写了一篇较长的博文:

谢谢你的链接,我发现你的博文非常有用。关于Java背景,您是对的。异常处理是Java编程不可或缺的一部分,因此我最终用@try@catch@填充Objective-C代码。我现在开始摸索正确的模式。