NSMutableArray memory leaks in recursive method - iphone

I have a recursive method that allocates an NSMutableArray, runs a recursive call and then releases the NSMutableArray. the method takes an array of numbers and a target value and then finds what combinations of the numbers can sum up to equal the target value e.g. target: 10, numbers: 5,5,4. the method returns an array of NSNumbers 5 and 5.
My problem is that a mutable array is always showing as a leak in the leaks instrument even though i am releasing it.
here is the recursive method:
-(NSMutableArray *) getCombsHelper:(NSArray *)numbers target:(int)target partial:(NSMutableArray *)partial {
int s = 0;
for (NSNumber *number in partial) {
s += [number intValue];
}
if (s == target)
[results addObject:partial];
if (s >= target)
return results;
for (int i = 0; i < [numbers count]; i++) {
NSMutableArray *remaining = [[[NSMutableArray alloc] init] autorelease];
int n = [[numbers objectAtIndex:i] intValue];
for (int j = i+1; j<[numbers count]; j++) {
[remaining addObject:[numbers objectAtIndex:j]];
}
//this is the array that is showing up as a leak.
NSMutableArray *partialRec = [[NSMutableArray alloc] initWithArray:partial];
[partialRec addObject:[NSNumber numberWithInt:n]];
[self getCombsHelper:remaining target:target partial:partialRec];
[partialRec release]; //the mutable array is released after the recursive call.
}
return results;
}
even if i autorelease it i am still getting it as a leak. Could this be a false positive leak? or is there something wrong i cant catch?

That method is odd;
results appears to be an instance variable that accumulate the results? That is generally odd; typically, you'll have something that calculates state into an ivar and a plain accessor that retrieves the ivar.
To expand: your recursive method is relatively expensive compared to a straight getter method. Say you need results in three places; if this recursive method is the only way to retrieve results, every call will incur calculation overhead. If, instead, you had something like:
- (void)combsHelper:...
- (NSArray*) results
{
return results;
}
Then you could do the calculation once and retrieve the results many times without incurring overhead (while you could do something like if (!results) [self combsHelper:...] in your getter, that'll lead to the getter causing mutation of state which is generally to be avoided -- best to separate the two).
don't name methods getSomething:...; get as a prefix is limited to a very specific use pattern (generally, pass by reference retrieval of a value -- uncommon)..
What array is leaking? Keep in mind that Instruments shows you the point of allocation of the leak, not where the real leak happens. If something is retaining the object elsewhere without a balanced release, that'll be your leak.
The leak is outside of this method; partialRec is being added to the results array. Something is probably retrieving it from said array, retaining it, and not balancing that with a release

Perhaps the complaint is that you pass partialRec to the method, then add it to an array (results), which you return, but you don't catch your return value.
Adding it to the array will retain it.
Where does 'results' come from anyway? I don't see its declaration.

You probably have a problem on this line:
[self getCombsHelper:remaining target:target partial:partialRec];
You are passing partialRec to another method, and it is not autoreleased.

Related

objective c perform selector in background and autoreleasepool

I am developing an iphone application which has some data stored in a sqllite database. When my view loads i would like to load the data from the database on a background thread. The problem is the application keeps crashing and i dont know why.
The code:
-(id) init
{
if((self=[super init]))
{
[self performSelectorInBackground:#selector(loadList) withObject:nil];
}
}
-(void) loadList
{
#autoreleasepool
{
Loader * loader = [[Loader alloc] init];
NSMutableArray * array = [loader getItemList];
[array retain];
NSLog(#"Got %d items",[array count]);
[self performSelectorOnMainThread:#selector(createList:) withObject:array waitUntilDone:false];
[loader release];
}
}
-(void) createList: (NSMutableArray*) array
{
items = array;
int i;
Item * it;
for(i = 0; i < [items count]; i++)
{
it = [items objectAtIndex: i];
[it getName]; // crashes
// populate the list
}
}
Loader returns a NSMutableArray with Item objects. The application crashes when i call the item getName (which returns a NSString*). From what i understand it crashes because the item name properties is being released. What am i doing wrong?
Thanks!
It's likely to be a problem with whatever type of object you're using to populate array.
I'm unable to find finger-on-paper proof but I'm confident that performSelectorOnMainThread:withObject:waitUntilDone: retains its object. However if each of the items in array keeps a reference to loader then they need to take responsibility for retaining that object. It looks like you're attempting to keep it alive manually but — as Chuck alludes to — your call to performSelector... will return instantly and not wait for the call you've made to complete.
This particular bug appears to be that you're passing waitUntilDone:NO, so the array is being released immediately and consequently so are its items.
But in general, UIKit is not thread-safe, so this is just a touchy design. I would probably put the loading of this stuff in another class that handles the task for you instead of right in the view.
I'd put a breakpoint on the line:
it = [items objectAtIndex: i];
Then type
po it
in the debugger, and see what's in the name field. As a guess, I'd say one of two things: 1) the field that getName returns isn't initialized with an object (i.e. isn't a real NSString *) or that you're getting a C string from SQLite (which is what it usually returns) and you're trying to treat it as an NSString *. If it's the latter you can use [myCString stringWithUTF8String] to convert the C string into an NSString *

sometimes crash EXC_BAD_ACCESS with no message (set NSZombieEnabled)

I'm handling RemoteIO to get mic inputs and modify them little.
Sometimes it crashes with EXC_BAD_ACCESS and there is no more message.
The lines that make crashes are these;
int currPower = [[powers objectAtIndex:i] intValue];
int prevPower = [[powers objectAtIndex:i - 1] intValue];
explaining the code,
"powers" is NSMutableArray.
[powers count] was always bigger than variable "i"
Struggling for a while, I found a good way to fix it.
A environment variables.
So I set NSZombieEnabled and also NSDebugEnabled so that I could see the reason of the crashes.
But even though I set the variables, Xcode shows no message.
(But it correctly shows messages when a crash occurs from other line.)
Also a weird thing is that it doesn't crash just after the start of run;
it crashes in a minute in average. (But the times really varied.)
And this is a little guess. When I decreased the rate to half than before,
it was more stable.
So, is it a problem with NSMutableArray, because NSMutableArray method couldn't catch up the speed of the rate?
or do you see some other possible reasons?
=========================================================================================
There are some more codes.
I allocated powers in this way..
powers = [[NSMutableArray alloc] initWithCapacity:POWER_ARRAY_SIZE];
where I release the powers array is..
- (void)dealloc {
[powers release];
[super dealloc];
}
and no where else.
more detailed code is this.
- (void)drawRect:(CGRect)rect
{
...//Do Something
...//Check "endindex" and "startindex" not to exceed boundary
for (int i = endindex; i > startindex; i-=1)
{
int currPower = [[powers objectAtIndex:i] intValue];
int prevPower = [[powers objectAtIndex:i - 1] intValue];
...//Doing something
}
}
this drawRect: method is calling from Main Thread(By Timer) in every millisecond.
--
updating(more specifically adding) powers in this method
- (void)setPower:(int)p
{
[powers addObject:[NSNumber numberWithInt:p]];
while ([powers count] > POWER_ARRAY_SIZE){
[powers removeObjectAtIndex:0];
}
}
and also this method is calling in every millisecond.
and this is calling in background thread.
so without #autoreleasepool XCode Shows message of alert of leaking
for this reason I blocked the method(setPower) with #autoreleasepool{..}
If NSZombies solved your problem it means that your NSMutableArray is being released somewhere, or it's in an autorelease pool. Also you could be trying to write outside the bounds of your array.
If the NSMutableArray is in an autorelease pool (it was created by a convenience method or you explicitly autoreleased it) manually retain it and release it when you no longer need it.
If the object is not in an autorelease pool check when the release is called for that object.
Write a simple warning before the assignment:
if( i <= 0 || i >= [powers count] ) NSLog(#"Here's the problem. i = %d", i);
I found the answer.
Crashes are occurred because NSMutableArray of objected-C sometimes ack wrong.
That's when I try to do something in every milliseconds with it.
So I changed the Objective-C array to C array, like
int power[ARRAYSIZE];
and after I changed it, it works fine.
May be NSMutableArray isn't that light to do something really fast.

How to release an object in a forin loop?

I'm new to cocoa / objective-c and i'm struggeling with the releases of my objects. I have the following code:
gastroCategoryList = [[NSMutableArray alloc] init];
for (NSDictionary *gastrocategory in gastrocategories) {
NSString *oid = [gastrocategory objectForKey:#"id"];
GastroCategory *gc = [[GastroCategory alloc] initWithId:[oid intValue] name:[gastrocategory objectForKey:#"name"]];
[gastroCategoryList addObject:gc];
}
The analyzer shows me that the "gastrocategory" defined in the for is a potential memory leak. But i'm not sure if i can release this at the end of the for loop?
Also at the following code:
- (NSArray *)eventsForStage:(int)stageId {
NSMutableArray *result = [[NSMutableArray alloc] init];
for (Event *e in eventList) {
if ([e stageId] == stageId) {
[result addObject:e];
}
}
return result;
}
The Analyzer tells me that my "result" is a potential leak. But where should I release this?
Is there also a simple rule to memorize when i should use assign, copy, retain etc. at the #property ?
Another problem:
- (IBAction)showHungryView:(id)sender {
GastroCategoriesView *gastroCategoriesView = [[GastroCategoriesView alloc] initWithNibName:#"GastroCategoriesView" bundle:nil];
[gastroCategoriesView setDataManager:dataManager];
UIView *currentView = [self view];
UIView *window = [currentView superview];
UIView *gastroView = [gastroCategoriesView view];
[window addSubview:gastroView];
CGRect pageFrame = currentView.frame;
CGFloat pageWidth = pageFrame.size.width;
gastroView.frame = CGRectOffset(pageFrame,pageWidth,0);
[UIView beginAnimations:nil context:NULL];
currentView.frame = CGRectOffset(pageFrame,-pageWidth,0);
gastroView.frame = pageFrame;
[UIView commitAnimations];
//[gastroCategoriesView release];
}
I don't get it, the "gastroCategoriesView" is a potential leak. I tried to release it at the end or with autorelease but neither works fine. Everytime I call the method my app is terminating. Thank you very much again!
In your loop, release each gc after adding it to the list since you won't need it in your loop scope anymore:
gastroCategoryList = [[NSMutableArray alloc] init];
for (NSDictionary *gastrocategory in gastrocategories) {
NSString *oid = [gastrocategory objectForKey:#"id"];
GastroCategory *gc = [[GastroCategory alloc] initWithId:[oid intValue] name:[gastrocategory objectForKey:#"name"]];
[gastroCategoryList addObject:gc];
[gc release];
}
In your method, declare result to be autoreleased to absolve ownership of it from your method:
NSMutableArray *result = [[[NSMutableArray alloc] init] autorelease];
// An alternative to the above, produces an empty autoreleased array
NSMutableArray *result = [NSMutableArray array];
EDIT: in your third issue, you can't release your view controller because its view is being used by the window. Setting it to autorelease also causes the same fate, only delayed.
You'll have to retain your GastroCategoriesView controller somewhere, e.g. in an instance variable of your app delegate.
BoltClock's answer is spot-on as to the first part of your question. I'll try to tackle the rest.
Assign is for simple, non-object types such as int, double, or struct. It generates a setter that does a plain old assignment, as in "foo = newFoo". Copy & retain will, as their names imply, either make a copy of the new value ("foo = [newFoo copy]") or retain it ("foo = [newFoo retain]"). In both cases, the setter will release the old value as appropriate.
So the question is, when to copy and when to retain. The answer is... it depends. How does your class use the new value? Will your class break if some other code modifies the incoming object? Say, for example, you have an NSString* property imaginatively named "theString." Other code can assign an NSMutableString instance to theString - that's legal, because it's an NSString subclass. But that other code might also keep its own reference to the mutable string object, and change its value - is your code prepared to deal with that possibility? If not, it should make its own copy, which the other code can't change.
On the other hand, if your own code makes no assumptions about whether theString might have been changed, and works just as well whether or not it was, then you'd save memory by retaining the incoming object instead of unnecessarily making a copy of it.
Basically, the rule, which is unfortunately not so simple sometimes, is to think carefully about whether your own code needs its own private copy, or can correctly deal with a shared object whose value might be changed by other code.
The reason you can release gc after it is added to the gastroCategoryList is that when an object is added to an array, the array retains that object. So, even though you release your gc, it will still be around; retained by the gastroCategoryList.
When you are returning a newly created object from a method, you need to call autorelease. This will cause the object to be released only after the runtime leaves the scope of the calling method, thereby giving the calling method a chance to do something with the returned value.
Note that if your method starts with the word copy or new, then you should not autorelease your object; you should leave it for the calling method to release.
As for copy vs retain vs assign... as a general rule, copy objects that have a mutable version, such as NSArray, NSSet, NSDictionary, and NSString. This will ensure that the object you have a pointer to is not mutable when you don't want it to be.
Otherwise, use retain whenever you want your class to be ensured that an object is still in memory. This will apply to almost every object except for objects that are considered parents of your object, in which case you would use assign. (See the section on retain cycles here).
Also note that you have to use assign for non-object types such as int.
Read through the Memory Management Programming Guide a bit; it's quite helpful.

NSMutableArray release objects inserted. -> cause memory leak

Hi I have a lot of problems to remove the objects of my mutable array.
I have a method which send back a mutable initialized with a custom object.
This mutable is declared like autorelease for releasing after method.
In my return, I retain the mutable to not loose it.
I want in this second method to remove the content of my mutable and release my mutable.
But my app quit and fail.
//first method which return my mutable
NSMutableArray *highScores = [[[NSMutableArray alloc] init]autorelease] ;
for (....)
{
HighScore *currentHighScore = [[HighScore alloc] init];
currentHighScore.user = name;
currentHighScore.score = score;
//add to the array
[highScores addObject:currentHighScore];
[currentHighScore release];
}
return highScores;
// method which use the first method
//retrieve with retain to keep.
highScoreList = [[HighScoreViewController getHighScores:NormalGameModeXML]retain] ;
HighScore *currentHighScore;
int count = [highScoreList count];
for (int i = 0; i < count ; i++)
{
currentHighScore = [highScoreList objectAtIndex:i];
}
This is working, but off course I have memory leak for all the objects in the mutable not released.
But if i'm trying to release the object of the mutable and the mutable itself by this :
//remove Mutable array content.
//[highScoreList removeAllObjects] ;
//[highScoreList release];
My app is quitting.
Do you have a solution to avoid the memory leak and clean it well?
Try using NSZombieEnabled to check the reason for an EXC_BAD_ACCESS..
HowTo is found here..
//[highScoreList removeAllObjects] ;
//[highScoreList release];
No need to removeAllObjects prior to release.
Note that if you use highScoreList after it is deallocated, your app will crash as you describe. I.e. if you use highScoreList after the above, BOOM.
You could set highScoreList to nil, but a better solution is to understand why you are using an object after you think you should be done with it.
And, as always:
If there is a crash, there is a backtrace. Post it.

Memory management in objective-c

I have this code in one of my classes:
- (void) processArray
{
NSMutableArray* array = [self getArray];
. . .
[array release];
array = nil;
}
- (NSMutableArray*) getArray
{
//NO 1:
NSMutableArray* array = [[NSMutableArray alloc]init];
//NO 2:
NSMutableArray* array = [NSMutableArray array];
. . .
return array;
}
NO 1: I create an array and return it. In the processArray method I release it.
NO 2: I get an array by simply calling array. As I'm not owner of this, I don't need to release it in the processArray method.
Which is the best alternative, NO 1 or NO 2? Or is there a better solution for this?
The method should return an autoreleased array, NO 2 is the better choice. The reason for this is that when you call the method with
NSMutableArray* array = [self getArray];
you will expect as a matter of convention to not have to release the array. If you want to take ownership of it, you retain it, but otherwise you shouldn't have to care about it. In Cocoa, you only take ownership by explicitly sending alloc or retain or copy (or new). Since the processArray method doesn't do that, it shouldn't have to take care of releasing the array.
So you should use NO 2, and also you should remove these two lines:
[array release];
array = nil;
If the array and its contents use a lot of memory or its used lots of times, you'll want to release them straight away, so use option 1. According to the Objective-C guidelines, you'll want to prefix the word "new" to your subroutine name instead of "get" in that case.
If on the other hand, you want to reduce the number of lines of code that say simply [array release]; or similar then use option 2.
It is simply a balance between reducing lines of code, and reducing unnecessary temporary memory use.
Whilst the autorelease pool will help in reducing memory leaks and make your code smaller, sometimes you need to explicitly release everything as it goes out of use to keep the use of memory down.
HTH
EDIT
Ah - I stand corrected. Reading the iPhone version of the Memory Management Programming Guide for Cocoa I see that the iPhone guidelines are to use a prefix of "new..." so for example "newArray" in this case, if the caller is supposed to manually release and NOT a prefix of "create...". "Creating" can refer either to creation of manually released or of automatically released objects and so would be ambiguous. Text corrected above.
- (void) processArray
{
NSMutableArray* array = [[self getArray] retain];
//Now you are the owner of array, so you take care to release it
. . .
[array release];
array = nil;
}
- (NSMutableArray*) getArray
{
//create a new array
//temporarily the method owns the array
NSMutableArray* array = [[NSMutableArray alloc]init];
//fill in here with elements or what you want
..........
[array autorelease];
//autorelease here says "I don't own the result
//if anyone cares about it, he should retain it himself
return array;
}
So in short when you create new objects you should autorelease them before returning.
Because if the calling method wants to use the result, the calling method should take care
of retaining and releasing the result.
It's always good to run the Klang static analyzer for this issues, when you are not really sure in your retaining/releasing code : http://clang-analyzer.llvm.org/