Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Executing cleanup code?

Tags:

objective-c

Generally speaking goto is bad (we all know why) What would be a better way to implement a simple cleanup on an error (as in the example below) without having to duplicate the code. To my mind the code below is fine, I was just curious what others would do:

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:

In general terms I agree that @try, @catch, @finally are more than certainly the way to go but I do have two small concerns.

(1) The three @try, @catch, @finally blocks must all be together, you don't have the flexibility to place code between the @catch and @finally that you might want to bypass.

(2) Apple's documentation for Obj-C 2.0 states the following: "Important: Exceptions are resource-intensive in Objective-C. You should not use exceptions for general flow-control, or simply to signify errors (such as a file not being accessible)".

much appcreciated

gary

like image 435
fuzzygoat Avatar asked Mar 01 '26 08:03

fuzzygoat


2 Answers

This is a common idiom in C code, and I don't think there is anything wrong with it in the absence of a language with more comprehensive creation/destruction semantics.

Goto is considered harmful in the general sense; it can make program execution difficult to follow. Here, it's very limited in scope, and the flow is unidirectional. It's also helpful in the sense that it allows you to localize your cleanup code, which is a good thing.

like image 58
Terry Mahaffey Avatar answered Mar 03 '26 22:03

Terry Mahaffey


Well, first of all I would try to refactor it into some more methods, maybe then the code would not be so illegible?

Also, you can always use autoreleased objects and so you only need the [pool drain] at the end. And this can probably be done using @try/@finally, so that you can just return 1 instead of returnCode = 1.

E.g. take a look at the Exception Handling and Memory Management document (I know your question is not about exceptions, but this is basically all the same) - they recommend something like this:

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

Personally, this is what I would do.

like image 26
Adam Woś Avatar answered Mar 03 '26 22:03

Adam Woś