Why do I have to call super -dealloc last, and not first?
Asked Answered
S

6

30

correct example:

- (void)dealloc {
    [viewController release];
    [window release];
    [super dealloc];
}

wrong example:

- (void)dealloc {
    [super dealloc];
    [viewController release];
    [window release];
}

Althoug in alsmost all other cases when overriding a method I would first call the super's method implementation, in this case apple always calls [super dealloc] in the end. Why?

Streusel answered 26/5, 2009 at 9:44 Comment(0)
O
55

Its just a guideline. You can call other instructions after [super dealloc]. however you can not access variables of the superclass anymore because they are released when you call [super dealloc]. It is always safe to call the superclass in the last line.

Also KVO and depended (triggered) keys can produce side effects if they are depended of already released member variables.

Osteitis answered 26/5, 2009 at 10:10 Comment(1)
With ARC, you don't have to call [super dealloc] at all, it produces a compiler error when you do.Bomke
R
12

I don't know anything about programming for the iPhone, but I would assume that it is for the same reason that destructors need to be called in reverse order. You want to make sure that all your 'garbage' is cleaned up before calling your superclass. If you do it the other way around things can get messy. For instance, if your destructor needs to access memory that the super destructor has already freed:

class X {
    private Map foo;

    function __construct() {
        foo = new Map();
    }

    function __destruct() {
        foo.free;
    }
}

class Y extends X {
    function __construct() {
        super.__construct();
        map.put("foo", 42);
    }

    function __destruct() {
        super.__destruct();
        if (map.containsKey("foo")) {    // boooooooooom!
            doSomething();
        }
    }
}

You may not encounter this problem in your code, because "you know what you're doing", but it is a safer and overall better practice not to do such things.

Radnorshire answered 26/5, 2009 at 9:51 Comment(4)
My guess is because it answered the question, at least partially. A downvote on the other hand commonly implies that the answer was unhelpful or just plain wrong. If it was wrong I would very much like to know why so I can learn from my mistake. Or were you just being polemic?Radnorshire
I didn't downvote it; it's a good answer. However, the downvote is fair enough since it's a guess, not specific to the Cocoa framework.Weathercock
@n3rd, I agree with @adam, it isn't a specific answer about cocoa/obj-cAnoa
If the problem is indeed of a general nature as I assumed, that is completely irrelevant. If you wonder why a method call on the "null object" is a bad idea, it doesn't matter if you're talking about Java, PHP, C++ or JavaScript.Radnorshire
G
5

[super dealloc] is freeing up the memory used by your object, including the pointers to viewController and window. Referring to variables after you've freed them is hazardous at best.

See this answer.

Gramercy answered 26/5, 2009 at 15:7 Comment(0)
P
2

Here is actual example where [super dealloc] must be last, otherwise the call to removeFromRunLoop will cause crash. I'm not sure what happens inside NSOutputStream's removeFromRunLoop, but it seems to access 'self' in this case.

Setup:

[outputStream setDelegate:self];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

Dealloc:

- (void)dealloc {
    if (outputStream) {
        [outputStream close];
        [outputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
                                forMode:NSDefaultRunLoopMode];
        [outputStream release];
        outputStream = nil;
    }
    delegate = nil;
    [super dealloc]; // must be last!
}
Preparedness answered 31/1, 2010 at 20:54 Comment(0)
P
1

You practically almost have [super dealloc] at the end because it frees up the variables of the superclass and they can no longer be accessed.

One exception is if you have a subclass of UITableViewController that is using another class as its table view delegate. In that case you have to release the table view delegate after [super dealloc] because the table view is referencing the table view delegate and the table view has to be released first.

Pelite answered 26/5, 2009 at 9:45 Comment(2)
Can you give a little more detail of your exception? It sounds slightly wrong to me.Lorant
@Mark: sounds wrong to me, too. Normally you wouldn't even retain the delegate on the first place to avoid retain cycles.Effluence
S
1

[to the last post] Wouldn't the tableView referencing the delegate be responsible for releasing it's own delegate? I would think it's retained it when set (so you could release or autorelease it) and it would take care of itself?

As for the OP question, I will always call super first if I'm constructing and call super last if I'm destructing. I think of it as "I want to have super build what it wants so I can build on that, and I want super to tear down last after I clean up after myself." Virtually all the calls I use are constructing though, except dealloc, so that's why you would see it last in my dealloc code always.

Scarborough answered 6/8, 2010 at 14:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.