Search code examples
iphoneobjective-ccocoamemory-leaksretaincount

Handling memory leaks in factory methods


I am developing an objective C framework which will ship as a static library at the end. But when I integrate that library to an actual application (by adding the static library) in the leaks tools I see some memory leaks present.

Here is an example scenario.

@implementation Test

@synthesize testNumber

+(Test) createTestInstance {

    Test *test = [[Test alloc] init];
    test.testNumber = [[NSDecimerNumber alloc] initWithInt:1];

    return test;
}

-(void) dealloc {
    [testNumber release];
}

@end

Although I release testNumber variable in dealloc I see a memory leak in Leaks tool at alloc position. What can be the issue here?

Also as this is a library provided for user to invoke, is it a best practice to release those variable from the library code?

Thank You


Solution

  • I see two problems here. If testNumber is a retain property, you are overretaining it with this statement:

    test.testNumber = [[NSDecimerNumber alloc] initWithInt:1];
    

    Both alloc-init and the property accessor are retaining the object. Therefore, it should be:

    test.testNumber = [[[NSDecimerNumber alloc] initWithInt:1] autorelease];
    

    There is no need to mention that you still need to release testNumber in the dealloc method.

    Also, I understand createTestInstance is a convenience constructor to create Testobjects and it should return an autoreleased object according to the Object Ownership Policy (only methods with names that start with “alloc”, “new”, “copy”, or “mutableCopy” return an object you own):

    + (id)createTestInstance {
    
        Test *test = [[[self alloc] init] autorelease];
        test.testNumber = [[[NSDecimerNumber alloc] initWithInt:1] autorelease];
    
        return test;
    }
    

    Finally, as suggested by @Josh Caswell, convenience constructors should return id instead of the specific class. From The Objective-C Programming Language:

    The return type of convenience constructors is id for the same reason it is id for initializer methods, as discussed in “Constraints and Conventions.”

    Also, they should use self instead of the hard-coded class name to alloc-init the instance in order to handle subclassing properly (self here refers to the class object itself since this is a class method).