执行清理代码?

时间:2010-01-10 20:24:52

标签: objective-c

一般来说goto很糟糕(我们都知道为什么)在不必复制代码的情况下,对错误实现简单清理(如下例所示)的更好方法。在我看来,下面的代码很好,我只是好奇别人会做什么:

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]
    int returnCode = 0;

    // ... Other code

    // WRITE: To file
    if([dataStore writeToFile:savePathData atomically:YES] == NO) {
        NSLog(@"writeToFile ... Error");
        returnCode = 1;
        goto cleanUpCode;
    }

    // ... Other code

    // Clean up
    cleanUpCode:
    [archiver release];
    [newPlanet release];
    [pool drain];
    return(returnCode);
}

EDIT_001:

总的来说,我同意@try,@ catch,@ finally不仅仅是肯定的方式,但我确实有两个小问题。

(1)三个@try,@ catch,@ finally块必须全部在一起,你没有灵活性在@catch和@finally之间放置你可能想要绕过的代码。

(2)Apple的Obj-C 2.0文档声明如下:“重要:在Objective-C中,异常是资源密集型的。您不应该使用异常来进行一般流量控制,或者只是表示错误(例如文件无法访问)“。

多得多的

加里

4 个答案:

答案 0 :(得分:5)

这是C代码中常见的习惯用法,在没有更全面的创建/破坏语义的语言的情况下,我认为它没有任何问题。

Goto在一般意义上被认为是有害的;它可以使程序执行难以遵循。这里,它的范围非常有限,流量是单向的。从某种意义上讲,它也可以帮助您本地化清理代码,这是一件好事。

答案 1 :(得分:4)

好吧,首先我会尝试将它重构为更多的方法,也许那么代码就不会那么难以辨认?

此外,您始终可以使用自动释放的对象,因此最后只需要[pool drain]。这可以使用@try / @finally来完成,这样您就可以return 1代替returnCode = 1

E.g。看一下Exception Handling and Memory Management文档(我知道你的问题不是关于异常,但基本上都是一样的) - 他们推荐这样的东西:

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

就个人而言,这就是我要做的事。

答案 2 :(得分:0)

有很多方法可以做到这一点。这是一对夫妇:

  1. 编写与您的主代码相对应的程序,例如: RunApplication。将调用放在“else”分支中。

  2. 将它放在try / catch中,在“catch”部分进行错误处理,否则进行正常处理。

  3. 代码

     e.g. try {
      .. check for error (any function/procedure that checks for an error can throw an exception
     .. do normal processing (still a good idea to factor this out into a procedure, for clarity
     }
     catch  {
         .. handle errors
     }
     finally
     {
         .. do cleanup
     }
    

    任何时候你认为你需要goto,对于错误情况,你可能会发现try / catch和exception更好。

    在没有try / catch的语言中,只需使用重构。

答案 3 :(得分:-1)

当你描述的东西看起来像一个小命令行程序时,我不会担心它。因为当你的程序结束时,程序分配的所有内存都将返回给系统(它将不复存在)。但是,如果你有一个更大的程序,分配了很多并运行了一段时间,你可能会更正确地考虑清理,因为它可以帮助追踪内存泄漏,这可能会影响运行较长时间的程序。在这种情况下,我还建议使用一些宏。

#define THROW( _name ) goto label_ ## _name
#define CATCH( _name ) label_ ## _name:

    :
    :

    if([dataStore writeToFile:savePathData atomically:YES] == NO) {
        NSLog(@"writeToFile ... Error");
        returnCode = 1;
        THROW( cleanUpCode );
    }

    :
    :

    CATCH( cleanUpCode )

    [archiver release];
    [newPlanet release];
    [pool drain];