views:

301

answers:

3

I've just completed my first simple iPhone app; I'm using Instruments to find memory leaks.

I am a little lost as to how to reuse pointers. I have read the Apple documentation, but I still don't understand the correct procedure.

The Apple docs say, "Another typical memory leak example occurs when a developer allocates memory, assigns it to a pointer, and then assigns a different value to the pointer without freeing the first block of memory. In this example, overwriting the address in the pointer erases the reference to the original block of memory, making it impossible to release."

Do I really have to release and create a new pointer each time?

Example creating memory leak on dateFormatter:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 

// year 
[dateFormatter setDateFormat:@"yyyy"]; 
NSInteger year = [[dateFormatter stringFromDate:date] integerValue]; 

// month
[dateFormatter setDateFormat:@"MM"];
NSInteger month = [[dateFormatter stringFromDate:date] integerValue];
...

[dateFormatter release];

Thanks for your help!

+7  A: 

There's no memory leak in this example. It's 100% valid. What Apple means in the documentation is something like this:

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy"];
NSInteger year = [[dateFormatter stringFromDate:date] integerValue];

// new instance of NSDateFormatter without releasing the old one
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"MM"];
NSInteger month = [[dateFormatter stringFromDate:date] integerValue];

[dateFormatter release];

Here are some tips to prevent these mistakes:

  1. Pay attention when reusing a pointer.
  2. Always use this construct: [[[NSDateFormatter alloc] init] autorelease] or use convinence members like [NSArray arrayWithCapacity:...] This is generally a good idea in Cocoa as the overhead is small. If you are on an iPhone this matters more. Apple recommends to manually release objects in order to keep memory low. But as always, profile first before optimizing.
  3. Don't use broad variable names like buffer that you are likely to reuse.
  4. Reusing variables does not save memory. The complier optimizes such things automatically.
Georg
Oh right, duh. Can't release the ints. Not actually doing that in my real code. ;)
wanderlust
Re-reading after more sleep. Can you explain what "profile first before optimizing" means please?
wanderlust
It's faster to use `release` instead of `autorelease`. But you are more likely to forget a `release`. Therefore you should use `autorelease` whenever possible and only use the more manual approach of using `release` when you can show that your program runs too slowly by using a profiler or a similar technique.
Georg
Okay, thanks much!
wanderlust
+1  A: 

This looks OK. You've only called alloc once to create one instance of NSDateFormatter and you release it at the end. In between you declare separate NSIntegers for year and month and call instance methods on dateFormatter. You're not reassigning its allocated memory with setDateFormat:.

Chris Newman
Except that he releases the `month` and `year` variables. That are just NSIntegers, not objects, so you don't have to release them, just like *gs* stated in his comment.
JoostK
Okay, thanks guys. I guess I'm misunderstanding the Instruments leak output. And btw, I'm a she. :D
wanderlust
Or instruments reports a non-error. This is possible but unlikely in such simple code.
Georg
To paraphrase Marge Simpson: "A lady coder? Now I've seen everything" :) :)
Chris Newman
A: 

Also, the analyze function in the new versions of Xcode will find "simple" leaks like this at compile time.

gerry3
Excellent, thank you!
wanderlust