Search code examples
objective-creleaseinitself

non-ARC: Should I call [super init] before [self release]?


I have a custom non-ARC init, and I wonder if I should call [super init] before releasing self.

Solution A, not calling [super init] before [self release]:

- (instancetype)initWithInteger:(NSInteger)anInteger
{
    if (anInteger == 0)
    {
        [self release];
        return nil;
    }
    self = [super init];
    if (!self)
        return nil;

    // Initialization code
    self.i = anInteger;

    return self;
}

Solution B, calling [super init] before [self release]:

- (instancetype)initWithInteger:(NSInteger)anInteger
{
    self = [super init];
    if (!self)
        return nil;
    if (anInteger == 0)
    {
        [self release];
        return nil;
    }

    // Initialization code
    self.i = anInteger;

    return self;
}

Solution

  • I would go with the second pattern. The reason for this is that super's dealloc might possibly rely on something in super's init having been done to work properly.

    Here is a (very) contrived example, this is the init and dealloc method in a class that you are subclassing.

    @implementation ASuperClass
    {
        char* foo;
    }
    
    -(id) init 
    {
        self = [super init];
        if (self != nil)
        {
            foo = strdup("blah blah blah");
        }
        return self;
    }
    
    -(void) dealloc
    {
        if (foo[1] == 'l')
        {
            NSLog(@"Second character was l");
        }
        free(foo);
    }
    

    In the above, if this is the class you inherited from, your first pattern will throw an EXC_BAD_ACCESS on a null pointer dereference.