Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does this Objective-C code leak memory?

One thing I'm concerned about is I create two ints, but don't release them. Would it be better to make them NSIntegers?

-(void) flipCoin {

    int heads = [headsLabel.text intValue];
    int tails = [tailsLabel.text intValue];

    if (random() %2 ==1 )
    {
        heads++;
    }
    else {
        tails++;
    }

    headsLabel.text = [NSString stringWithFormat:@"%d", heads] ;
    tailsLabel.text = [NSString stringWithFormat:@"%d", tails];

}
like image 680
node ninja Avatar asked Jul 02 '26 06:07

node ninja


2 Answers

As sha notes, local variables get allocated in the current stack frame. As soon as the current function call returns, the stack gets "popped", and the memory occupied for the current call is not released so much as abandoned, until it is overwritten by the next call that gets pushed into that part of the stack.

So why do we have to release variables like this:

MyClass *myObject = [[MyClass alloc] init];

Well, you actually don't have to worry about "myObject". It's on the stack, just like your ints, and it will get cleaned up when the current call finishes.

What you have to worry about is the memory that myObject—which is a pointer—points to. It's off somewhere on the heap. Constructing an object involves asking the runtime for some semi-permanent place to put it; that process returns a memory address, which your pointer stores.

alloc and release are Objective-C idioms that largely replace C's malloc() and free() functions, but all of them ultimately are asking the computer to set aside memory on the heap, and all of that memory must ultimately be returned, either through an autorelease pool, a release message, or a free() call.

like image 78
Seamus Campbell Avatar answered Jul 03 '26 20:07

Seamus Campbell


int is what is known as a primitive type. It is not a pointer to an Objective-C object so you cannot release it. You can't even send a message to it.

NSInteger is also a primitive type in the sense that it is a typedef to a primitive type (long usually). So you can't release that either.

What do you need to release? You need to release any object you obtained by sending new, alloc or a method containing copy. You also need to release objects to which you have sent retain. So all of the local variables in the following must be released:

-(void) foo
{
    NSString* aString  = [[NSString alloc] init];
    NSString* aString2 = [aString copy];
    NSString* aString3 = [someOtherString retain];
    NSString* aString4 = [@"some string" copy];
}

NB due to implementation details, you would actually get away with not releasing the aString4 but you don't need to worry about it.

like image 37
JeremyP Avatar answered Jul 03 '26 19:07

JeremyP