iPhone Memory Debugging - iphone

I'm using Instruments to try to determine if there are places in my application that I could be more efficient with use of memory. I've taken the time to get somewhat familiar with Instruments but I'm generally a newbie with hunting memory management issues having come from a Java background. I seem to be using about 1.82mb by calls to this method:
+ (NSString *)stringFromDateWithFormat:(NSDate *)date withFormat:(NSString *)format
{
NSDateFormatter *dateFormatter;
NSString *result;
if (nil == date || nil == format)
return nil;
result = nil;
if (nil != (dateFormatter = [[NSDateFormatter allocWithZone:[self zone]] init])) {
[dateFormatter setDateFormat:format];
if (nil != (result = [dateFormatter stringFromDate:date])) {
[dateFormatter release];
return result;
}
[dateFormatter release];
}
return nil;
}
As I'm releasing the date formatter I'm wondering if the NSString result is my issue. It seems to me that the stringFromDate library call would return an autoreleased object so there's nothing I can do to 'manually' manage it. A bit unsure of how to optimize this method.

Is this method getting called a lot of times in a loop? Autoreleased objects only get released when the NSAutoreleasePool they're in gets released. As I understand it, the default autorelease pool is created and release every event loop. It's possible you're creating too many autoreleased objects in the course of a single event loop. The solution is to create your own NSAutoreleasePool in an appropriate place, and release it to clear up autoreleased objects. An extreme example that illustrates the point:
int i;
NSAutoreasePool* pool = nil;
for (i = 0; i < 1000000; ++i) {
/* Create a new pool every 10000 iterations */
if ((i % 10000) == 0) {
if (pool) [pool release];
pool = [[NSAutoreleasePool alloc] init];
}
[someObj someMethodThatCreatesAutoreleasedObjects];
}
[pool release];
In that example, the current pool is released every 10,000 iterations and a new one is created. You can read more about memory management in the Memory Management Programming Guide section on autorelease pools.

You need to return an autoreleased object anyway, so there's really nothing you should be doing about the result string. I don't see any mistakes related to memory, but your code is definitely more verbose than needed. Keep in mind that in Objective-C, if you call a method on nil, you get back nil (or 0 for an integer, but not for floating point values). You can take out all those if statements and the two return paths, and your code will still work the same way. Also, I would just use alloc instead of allocWithZone.

I am not a 100% with this. I am also just learning Mac/Iphone development. But you can use the auto release pool to help with memory management. It is used to get around release problems.
Here is an article with lots on memory management. Check out the left sided menu.

Related

retainCount shows MaxInt

After trying to print retainCount of object I get 2147483647. Why do I get such a result? It should be 1, shouldn't?
NSString *myStr = [NSString new];
NSUInteger retCount = [myStr retainCount];
NSLog(#"refCount = %u", retCount);
2011-09-08 17:59:18.759 Test[51972:207] refCount = 2147483647
I use XCode Version 4.1. Tried compilers GCC 4.2 and LLVM GCC 4.2 - the same result.
Garbage Collection option was set to unsupported.
NSString is somewhat special when it comes to memory management. String literals (something like #"foo") are effectively singletons, every string with the same content is the same object because it can't be modified anyway. As [NSString new] always creates an empty string that cannot be modified, you'll always get the same instance which cannot be released (thus the high retainCount).
Try this snippet:
NSString *string1 = [NSString new];
NSString *string2 = [NSString new];
NSLog(#"Memory address of string1: %p", string1);
NSLog(#"Memory address of string2: %p", string2);
You'll see that both strings have the same memory address and are therefore the same object.
This doesn't directly answer your question, but retainCount is not really all that useful and should not be used for testing. See this SO post for details.
When to use -retainCount?
While NSString's are an odd case (there are others in the framework) you might also run across this in other clases - it's one of the ways of creating a singleton object.
A singleton only exists once in the app and it's pretty important that it never gets released! Therefore, it will overwrite some methods of NSObject including (but not limited to):
- (id)release {
// Ignore the release!
return self;
}
- (NSUInteger)retainCount {
// We are never going to be released
return UINT_MAX;
}
This object can never be released and tells the framework that it's a singleton by having a ludicrously high retain count.
Checkout this link for more information about singleton objects.
I've seen this a couple of times regarding NSStrings, the retainCount returns the maximum count instead of the actual one when you try to look at retainCounts of strings in this manner.
Try this;
NSString *myStr = [[NSString alloc] init];
NSUInteger retCount = [myStr retainCount];
NSLog(#"refCount = %u", retCount);
Edit: Restored NSUInteger

What is the Ideal way to return data from function without leaking memory?

In IPhone Development ObjC , I wonder what is the right approach for functions to return some values in Dictionaries or Arrays. I mean should they return autorelease objects, but wouldn't it be bad if I am using too many functions to return values, like getUserRecordsFromDB() function will return all the user records, so should they return me autorelease objects? also when I am calling them multiple times, suppose with a span of 4 seconds to get the newely updated data. Can somebody let me an ideal scanario of how to get data from a function called frequently in the flow of program, and not leaking the memory.
We should always return autorelease objects from functions and ensure they get released by setting up Autorelease pool in the calling function as follows
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Call database function here...
[pool release];
Refer the auto release pool documentation here
If the method is in same class use global variable, if it is in some other class make sure it is allocated only one time, reuse the same memory every time it call that method.
Also check NSAutoreleasePool
Yes you should use autoreleased objects as return values.
You should stick to the cocoa programming guidelines.
This is a place to start, but there is a lot more to find on the subject.
You can always pass a mutable object to be filled in.
-(void) getMoreUsers:(NSMutableArray *)ioArray {
for ( ... ) {
NSMutableDictionary *user = [NSMutableDictionary new];
// fill in user ...
[ioArray addObject:user];
[user release]; // explicit release so only reference is owned by ioArray
}
}
This gives you explicit control when you know the lifetime of an object, but makes it easy to write a wrapper when you want to use autorelease.
-(NSArray *) getUsers {
NSMutableArray *result = [NSMutableArray array]; // implicit autorelease
[self getMoreUsers:result];
return result;
}
An example of using this with a known lifetime would be:
-(void) operateOnUsers {
NSMutableArray *array = [NSMutableArray new];
[self getMoreUsers:array];
// do stuff that will not retain array
[array release];
}

How does autoreleasing work in Objective-C?

I am just reading through the Practical Memory Management guide.
I am somewhat confused by this block of code:
- (void)printHello {
NSString *string;
string = [NSString stringWithFormat:#"Hello"];
NSLog(#"%#", string);
}
It seems to me that string is going to have a reference count of 0. Is this true?
What stops string from being deallocated before we call NSLog(string)?
Is this somehow equivalent to this:
- (void)printHello {
NSString *string;
string = [[[NSString stringWithFormat:#"Hello"] retain] autorelease];
NSLog(#"%#", string);
}
Edit: Similarly this code is given in the Practical Memory Management
guide:
- (NSString *)fullName {
NSString *string = [NSString stringWithFormat:#"%# %#", firstName, lastName];
return string;
}
When and how does the return value get freed? Who is the owner? Does the caller of fullName need to release the string returned by full name?
Strictly speaking,
- (void)printHello {
NSString *string;
string = [NSString stringWithFormat:#"Hello"];
NSLog(#"%#", string);
}
Is not equivalent to
- (void)printHello {
NSString *string;
string = [[[NSString stringWithFormat:#"Hello"] retain] autorelease];
NSLog(#"%#", string);
}
The convention is that a method should autorelease any object it returns. The only exception (AFAIK) is for constructors, which return an object with a +1 retain count. Since [NSString stringWithFormat:] returns an object. In first snippet, stringWithFormat: returns an already autoreleased object. the second snippet, you're retaining it once more and it'll be released twice (which has the same effect, but the second retain/autorelease pair is redundant).
Ok, now to answer your question. Essentially, every time UIKit calls your code, it creates an NSAutoreleasePool object. Every time you autorelease an object, its added to this pool. Finally, when your code returns back to UIKit, it calls the drain method on the pool (i.e [pool drain]) and that releases every object which has been added to the pool and deallocates the pool. Also, autorelease pools can be nested, so you can create your own pools and drain them if you're going to be creating a lot of autoreleased objects. It isn't as complicated as it sounds.
I'd highly recommend that you read the Autorelease Pools chapter in the Memory Management Guide (Which incidentally, comes right after the Practical Memory Management chapter).
First of all:
NSLog(string);
Don’t do this. (I just realized it comes right from the Apple docs. Weird.) The first argument to NSLog is the formatting string. If your string contains some percent escapes, bad things will happen. The correct, if slightly longer way is:
NSLog(#"%#", string);
Now to the point: Autoreleased objects do not have zero retain count. They have retain count 1+ and have a pending –1 operation on them that will happen “soon in the future”.
The precise meaning of “soon in the future” depends on the situation. If you’re on the main thread and there is no additional autorelease pool in place, autoreleased objects will be released on the next runloop iteration. This does not have to be the case if you have an additional release pool:
// Let’s pretend this is a long loop and you don’t want to wait
// for the autoreleased objects to be collected by the main pool.
for (…) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *foo = [NSString stringWith…];
[pool drain];
// Now foo is no longer valid.
}
As for returning autoreleased objects, that’s one of the main use cases for autoreleasing. You are returning an object that will perish “soon”, but if the caller is interested, he can retain and take over the ownership. (It’s like, if you pardon the image, passing a bomb with a burning safety fuse. If the caller is interested, he’ll put out the fuse by retaining.) And if the caller is not interested, like maybe he’s ignoring an output from a function or just uses the value to construct some other object, he does not do anything and the object will get out of memory:
- (id) createObject {
return [NSString stringWith…];
}
- (void) interestedCaller {
NSString *value = [[self createObject] retain];
}
- (void) notInterestedCaller {
[self createObject]; // maybe just interested in side effects
NSString *differentString = [NSString stringWithString:[self createObject]];
}
This is really convenient and makes the manual memory management quite pleasant. You might be interested in run loops and the Objective-C tutorial by Scott Stevenson.

Release in iPhone

Whenever I read about how to avoid memory leaks, I always came across a concept that
"Number of alloc must be equal to number of release".
But I came across a concept where we require more than one release. Like What I used to practise was as follows:
(NSString*) func1
{
NSString* result = [[NSString alloc] initWithFormat:#"Test String"]];
return result;
}
(void) func2
{
NSString* temp = [self func1];
[temp release];
}
But I came across a concept of retain count which says that in the above case the memory is not deallocated for the string since the retain count for the string is 1 at the end. So the right practise is
(NSString*) func1
{
NSString* result = [[NSString alloc] initWithFormat:#"Test String"]];
[result autorelease];
return result;
}
(void) func2
{
NSString* temp = [self func1];
[temp release];
}
So now I have two releases for deallocating the memory which is a contradictory to my above sentence which I read on most of the blogs ""Number of alloc must be equal to number of release".
I am little bit confused about the above stuff. Becoz if I autorelease the string in the first function and want to use the string in second function for a long time, and what if the release pool is flushed in between, on the other side if I dont use autorelease it will still block the memory.
So whats the correct way of doing it.
At the time you call alloc whatever is returned will have a retainCount of 1. Calling release on that object will cause it to be deallocated (it's retainCount will drop to 0). In your first example, then, the second line of func2 will deallocate the NSString* you received from func1, and your memory management chores are complete.
In the second example you are tossing result in func1 into the current autorelease pool, which will cause it to become deallocated when the pool drains. You do not want to attempt to manage the memory of that object once it has been placed into the pool- it is no longer your responsibility.
If you want to generate the string and keep it around for a while (e.g., through the lifetime of several autorelease pools), I would recommend the first form of memory management.
The correct way is this:
(NSString*) func1 {
NSString* result = [[NSString alloc] initWithFormat:#"Test String"];
// retaincount == 1
return [result autorelease];
}
(void) func2 {
NSString* temp = [self func1];
// retaincount == 1
// temp is autoreleased, therefore no [release] is necessary.
}
Autorelease is automatically done at the end of the run loop, that means it cannot be emptied while your code is doing something. -> The code you have is safe. This isn't true for multithreaded application!
(NSString*) func1
{
NSString* result = [[NSString alloc] initWithFormat:#"Test String"]];
return result;
}
[result retainCount] is 1
(void) func2
{
NSString* temp = [self func1];
[temp release];
}
[temp retainCount] is 0
No need for autorelease.
From Memory Management Rules:
This is the fundamental rule:
You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message. You are responsible for relinquishing ownership of objects you own using release or autorelease. Any other time you receive an object, you must not release it.
The following rules derive from the fundamental rule, or cope with edge cases:
As a corollary of the fundamental rule, if you need to store a received object as a property in an instance variable, you must retain or copy it. (This is not true for weak references, described at “Weak References to Objects,” but these are typically rare.)
A received object is normally guaranteed to remain valid within the method it was received in (exceptions include multithreaded applications and some Distributed Objects situations, although you must also take care if you modify the object from which you received the object). That method may also safely return the object to its invoker.
Use retain in combination with release or autorelease when needed to prevent an object from being invalidated as a normal side-effect of a message (see “Validity of Shared Objects”).
autorelease just means “send a release message later” (for some definition of later—see “Autorelease Pools”).
In general, I'd feel safer to do a retain on a return value, like the one in the "func 2":
(NSString*) func1 {
NSString* result = [[NSString alloc] initWithFormat:#"Test String"];
return [result autorelease];
}
(void) func2 {
NSString* temp = [[self func1] retain];
// Do something with temp
[temp release];
}
Is this unnecessary? I understand that in this example "temp" is just a local variable. But it could have been an instance variable, which may need to be retained.

Strange iPhone memory leak in xml parser

Update: I edited the code, but the problem persists...
Hi everyone,
this is my first post here - I found this place a great ressource for solving many of my questions. Normally I try my best to fix anything on my own but this time I really have no idea what goes wrong, so I hope someone can help me out.
I am building an iPhone app that parses a couple of xml files using TouchXML. I have a class XMLParser, which takes care of downloading and parsing the results. I am getting memory leaks when I parse an xml file more than once with the same instance of XMLParser.
Here is one of the parsing snippets (just the relevant part):
for(int counter = 0; counter < [item childCount]; counter++) {
CXMLNode *child = [item childAtIndex:counter];
if([[child name] isEqualToString:#"PRODUCT"])
{
NSMutableDictionary *product = [[NSMutableDictionary alloc] init];
for(int j = 0; j < [child childCount]; j++) {
CXMLNode *grandchild = [child childAtIndex:j];
if([[grandchild stringValue] length] > 1) {
NSString *trimmedString = [[grandchild stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[product setObject:trimmedString forKey:[grandchild name]];
}
}
// Add product to current category array
switch (categoryId) {
case 0:
[self.mobil addObject: product];
break;
case 1:
[self.allgemein addObject: product];
break;
case 2:
[self.besitzeIch addObject: product];
break;
case 3:
[self.willIch addObject: product];
break;
default:
break;
}
[product release];
}
}
The first time, I parse the xml no leak shows up in instruments, the next time I do so, I got a lot of leaks (NSCFString / NSCFDictionary).
Instruments points me to this part inside CXMLNode.m, when I dig into a leaked object:
theStringValue = [NSString stringWithUTF8String:(const char *)theXMLString];
if ( _node->type != CXMLTextKind )
xmlFree(theXMLString);
}
return(theStringValue);
I really spent a long time and tried multiple approaches to fix this, but to no avail so far, maybe I am missing something essential?
Any help is highly appreciated, thank you!
The issue is likely in this line:
[self.mobil addObject:[product copy]];
By calling for a copy of product you're creating a new NSMutableDictionary instance with a retain count of 1. The mobil instance, however, will increment the copy's retain count when you send it the addObject: message, so the retain count of the copy is now 2. Generally speaking, an object is responsible for handling its own object memory, so any time you message setFoo: or addObject:, you can just pass the object directly, even if its autoreleased or you are planning to release it right after the call; it is the receiver's responsibility to retain the object you're passing if it needs to hold onto it.
Because you did not assign the copy to any variable, you do not have a pointer that you can use to decrement the copy's retain count now that you're no longer interested in it, so even if mobil releases the product copy at some point, the copy will never reach a retain count of 0. Your [product release] statement at the end of the for loop releases the original product object, not the copy you created.
Instead, try the following and see if instruments is happier:
[self.mobil addObject:product];
In simple terms, every time you use copy, you also have to use release/autorelease somewhere.
And in this instance, the even easier answer is to not use copy in the first place, since you aren't doing anything with the original version of product after you've copied it.
I fixed the problem myself. It was kind of stupid, but maybe someone might come across the same thing, so I am going to post it here.
1) I had mutable array set up as instance variables like this:
#interface XMLParser : NSObject {
// ...
NSMutableArray *mobil;
// ...
}
#property(nonatomic, retain) NSMutableArray *mobil;
#end
Everytime I wanted to restore new data inside I did:
self.mobil = nil;
Which did not what I wanted to do, so this is the better approach:
[self.mobil removeAllObjects];
2) The dealloc method has to be like this to fix the leaks (because mobil is defined as a property):
-(void)dealloc {
[mobil release];
self.mobil = nil;
}
Whew, that has been a lot of work to find out - hope it saves someone else some time :-)