I'm just investigating some memory leaks in my app, I'm using Xcode 4.0.2. I've run the Analyze tool in Xcode and a good few memory leaks have been identified. I'm relatively new to Objective-C, this is my first app. I've pasted the code here:
http://pastie.org/3155043
I've added comments to the above code, where the memory leaks are occuring.
Memory Leak One: Method returns an Objective-C object with a +1 retain count (owning reference).
Memory Leak Two: Object allocated on line 248 and stored in 'imagesNames' is not referenced later in this execution path and has a retain count of +1 (object leaked).
Memory Leak Three: Potential leak of an object allocated on line 246 and stored into 'cmpWordoutStr'.
Any help appreciated.
Regards,
Stephen
You might want to consider using Automatic Reference Counting in your project.
I asked a question the other day on here, as I wasn't sure that it was a good idea, but the answers convinced me that it really is a step forward and is well worth taking advantage of:
To ARC or not to ARC? What are the pros and cons?
Hope this helps :)
Leak 1) You don't show the return or identify which variable is returned, so not possible to definitively diagnose this one.
Leak 2) You alloc/init an NSString and assign it to a variable that is never released. This is wrong for two reasons:
For each alloc there must be a corresponding release somewhere.
There is no point in doing alloc/init on an empty string. If you want an empty string just use #"".
Leak 3) Basically the same as (2).
(You really need to get a good book on Objective-C programming and study and restudy the section on storage management. Otherwise you'll be stumbling around in the dark.)
You're allocating an object first
NSString *cmpWorkoutStr = [[NSString alloc] init];
and then reassign the pointer without freeing the memory:
cmpWorkoutStr = [cmpWorkoutStr stringByAppendingString:indWorkoutStr];
hence the leak.
I didn't analyze your code in depth, but I guess you actually want NSMutableString there.
As Tom Andersen suggested above I used auto release and this solved the problem, example below:
NSString *cmpWorkoutStr = [[[NSString alloc] init] autorelease];
NSString *imageNames = [[[NSString alloc] init] autorelease];
Regards,
Stephen
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Understanding reference counting with Cocoa and Objective-C
I'm little confused with memory leaking - when I have to release object, and when it will be released automatically in iOS, so please help me understood using following code.
I have one method with following while block:
-(void) oneMethod {
NSMutableArray *returnValue = [[[NSMutableArray alloc] init] autorelease];
while(true) {
...
MyObject *myObj = [[MyObject alloc] initWithFrequency:100];
[returnValue addObject:myObj];
[myObj release];
...
}
}
Do I have to call [myObj release] or it will be released automatically in each loop?
Also, do I have to put autorelease in NSMutableArray init call, or it will be automatically released immediately after I return from method?
Thank you!
You should be using ARC - Automatic Reference Counting then you won't need to worry about releasing your allocated objects.
Your code is correct.
I find that as you work more with it you will get used to it. I don't spend much time thinking about it.
Generally, you need to release everything (or autorelease) you make.
Your loop is coded correctly in that its easy on memory, even for large arrays.
The sooner, the better is what I learned. Your example is appropriately releasing each myObj variable once inserted into the array. The array now "owns" the object and the object will exist as long as the array exists, no reason for the variable reference to remain.
ARC does seem to make all this completely unnecessary. I wonder how many developers will even learn this concept in the near future as ARC does it all for you now.
Presumably, you are not using ARC and so, if you did not call [myObj release] it would result in a leak each time through the loop.
I'm currently profiling my app and coming across a few leaks. I've tried releasing objects all over the place where I think they are needed. Each release has crashed the app.
Here's one line that I think is the culprit:
NSDictionary *dicUserData = [NSDictionary dictionaryWithObject:self forKey:#"chapter"];
Just wondering the best way to deal with this. I'm having issues with other leaks too that are kind of similar. It's worth noting that self is a custom class [Dal_Chapter].
Do I need to implement copy or something, call that in the above line and do autorelease on that?
Thanks in advance.
Using convenience methods such as dictionaryWithObject provide an autoreleased instance of the dictionary object. Unless you're retaining it elsewhere this is not where your leak is.
I would check out the static analyser it should be able to point out your leaks for you.
That dictionary will retain self so you shouldn't have to worry about it.
Is the owner of self releasing it ?
Basicly you don't have to do anything whith your dictionnary, but if you want to take control of the memory you'll need to do this :
NSDictionary *dicUserData = [[NSDictionary alloc] initWithObjects:yourObject forKeys:key];
and int your dealloc method,
[dicUserDate release];
But normaly you just have nothing to do... Are you sure that your leak come from your dictionnary ?
always keep all variables release in dealloc method. is it not in proper place it may be crash .check this link click here
I see that many people are allocating and releasing NSStrings.
I understand that the benefit is that the string is being released immediately and not by autoRelease.
my questions :
does it effective and should i always prefer allocating and releasing on autoRelease?
what is more expansive - allocating and releasing immediately and then allocating again OR allocating, using and releasing in dealloc.
will appreciate any explanation.
Thanks
shani
In most cases it does not matter. I think you should use the autorelease since it makes the code more simple and the #"string" shortcut is very elegant.
The basic difference is the point in time when the release happens. Like I said, in most cases it does not make any difference. If you want to control the release time more closely, then you can also do that for autorelease by rolling your own NSAutoreleasePool pool.
I don't see how you could re-use a NSString. Reusing a NSMutableString instance might be slightly faster the recreating it but you won't see the difference. Focus on simplicity and maintainability of your code.
I think your question is wether to use [[NSString alloc] init] or [NSString string]. As long as performance is not an issue, always go with the simplest one. That would be the autoreleased version, because you don't need to release it yourself.
I want to ask some question about the iPhone or objective C. What is 'garbage collected environment'? Thank you very much.
Expanding on Mr. Witherspoon's answer, you must alloc (allocate) and release memory space for some objects in your code. To practice good memory management, anything you have an alloc for you must have a matching release. For example:
NSString *string = [[NSString alloc]initWithFormat:#"%#", something];
/* ... some code ... */
[string release];
As you can see, my string is allocated some memory space but I release it programmatically when I won't need it anymore.
Garbage collection is a feature of the Objective-C runtime on the Mac and is not yet available on the iPhone. There, it basically means that you don't have to worry as much about memory management and handling retain / release cycles.
Is there anyway to get int (or float) numbers into a NSString object without using alloc and a subsequent release?
int myInt = 25;
NSString *myString = [[NSString alloc] initWithFormat:#"%d",myInt];
...
[myString release];
EDIT:
Thanks for the answers, I should have been a little more clear in the question, I am particularly interested in using this on the iPhone. As #chuck stated I could use a convenience method, but I was under the impression that I should be avoiding these where possible on the iPhone for memory / performance reasons. I could be wrong though.
gary
There's no way to create an NSString without creating it at some point. But you could use a convenience constructor so you don't have the burden of ownership.
NSString *myString = [NSString stringWithFormat:#"%d", myInt];
It will still be created and destroyed (as everything must be), but you don't have to do it yourself.
I could use a convenience method, but I was under the impression that I should be avoiding these where possible on the iPhone for memory / performance reasons.
The “performance reason” is the cost of autoreleasing an object. This was, at one time, expensive on an iPhone. (I don't know whether it still is.) The only alternative is explicitly allocating it and releasing it yourself. As others have pointed out, you can't have an object without having allocated it, and you mustn't allocate it without releasing it. You need both things to happen one way or another.
The memory reason is simply that an autoreleased object lasts longer—specifically, until the autorelease comes due. Autorelease many objects, and your memory usage will pile up; pile it up high enough, and SpringBoard will tell your app to knock it off (and/or just kill it). The solution is to make the objects not last so long, which means either (1) creating and draining your own autorelease pool around a known batch of objects or (2) managing the objects' lifetimes (that is, allocating and releasing them) yourself.
This latter reason is not specific to the iPhone—it affects the Mac as well, although our ceiling is higher: Macs have more short-term memory, plus virtual memory, so we can get away with more memory usage. Even so, we Mac programmers should also try not to waste memory, partly because paging hell wrecks one's day, and partly because we will get email from users if our apps sit too high in the Activity Monitor list.
NSString *mystring = [NSString stringWithFormat:#"Hello: %d",myint];
it should be autoreleased if you create it this way
i think the convention is that unless you see the word init or alloc in the method name then it should return an autoreleased object. i.e. the object is added to the current autorelease pool and flushed when the app advances to next stage in lifecycle
You want
NSString *aStr=[[NSNumber numberWithInt:myInt] stringValue];
It returns an autoreleased string.
You could use an NSMutableString (-appendFormat:) or a standard C-string. However, fundamentally, no, you're going to have to allocate memory somewhere.
Why not define a macro... something like
#define intString(i1) [[[NSString alloc] initWithFormat:#"%d",i1] autorelease];
put it in your prefix header.
Most of the time autorelease will have zero impact on your app's overall memory usage. You only need to be concerned with autorelease if you're accumulating many object instances. For example:
for (int i = 0; i < 1000; ++i)
{
NSString* s = [NSString stringWithFormat:#"%d", i];
...
}
That example will accumulate at least 1000 different string instances before anything is released, which is not desirable. That's a situation where you would look for alternatives.
If you wanted to avoid creating a bunch of string instances you could use NSMutableString:
NSMutableString* s = [NSMutableString stringWithCapacity:20];
[s appendFormat:#"%d", 123];
...
[s setString:#""];
[s appendFormat:#"%d", 456];
...
It's questionable whether that's any faster than simply creating and releasing separate string instances, but that pattern may fit better with what you're trying to accomplish in your code.