NSMutableArray memory Management when allocated directly - iphone

I know that when we add an object obj into a NSMutableArray, it takes the co_ownership of that object. So we can release the object obj just after adding that into the NSMutableArray. And when we release the NSMutableArray, it also calls the release of all the objects in it. So there is no memory leak and every thing is fine.
My doubt is if do like
NSMutableArray myArray = [[NMutableArray alloc] init];
[myArray addObject:[MyClass alloc] init]];
[myArray release];
Will this Cause any memory leak in our program?

Yes indeed, it will cause a memory leak.
The offensing line is (I have splitted it for clarity):
[myArray addObject:
[[MyClass alloc] init] // <- An instance is allocated with ownership
]; // <- The array retains the instance
At the end, the retain/release ownership are not balanced and causes the leak.
One solution is to make the allocation before the addition:
MyClass *obj = [MyClass alloc] init];
[[myArray addObject:obj];
[obj release];

Put autorelease for your MyClass. That should fix any memory leaks
NSMutableArray myArray = [[NMutableArray alloc] init];
[myArray addObject:[[[MyClass alloc] init] autorelease];
[myArray release];

Related

Releasing Object is it necessary?

I am stuck in the middle of memory management stuff. Please help me out in solving my question.
NSMutableArray *array = [[NSMutableArray alloc]init];
Object *obj = [[Object alloc]init];
[array addObject: obj];
[obj release];
Is it necessary to release obj in above code?
The answer to your question is: yes, if you don't use ARC. If you are writing a new app, you should seriously consider using ARC.
Container objects in Objective-C always balance their retain/release count. In other words, you should always manage memory as if you did not add the object and make sure your own code balances its retain count. Note that this is a convention and is not enforced, but you could always trust the built-in classes to follow this convention. Also, you can perform a static analysis (Cmd+Shift+B in XCode) to detect these problems. It would have pinpointed this in your code above.
The correct code in the case above would be:
NSMutableArray *array = [[NSMutableArray alloc]init];
Object *obj = [[[Object alloc]init]autorelease];
[array addObject: obj];
or
NSMutableArray *array = [[NSMutableArray alloc]init];
Object *obj = [[Object alloc]init];
[array addObject: obj];
[obj release];
since NSMutableArray (and its cousins) will retain the object as long as it is in the collection.

NSMutableArray: Memory management while calling methods

In my iOS app, I am using a NSMutableArray, named imageMArray. I have set its getter and setter properties and instantiated it.
In viewDidLoad:
imageMArray=[[NSMutableArray alloc] initWithArray:CategoryImages];
imageMArray=[self shuffleOnlyArray:imageMArray];
In ShuffleOnlyArray Method:
NSMutableArray *destArray1 = [[NSMutableArray alloc] initWithCapacity: [sourceArray count]] ;
return destArray1;
In shuffle Method:
imageMArray=[[self shuffleOnlyArray:imageMArray] retain];
There appears to be a memory leak in the Shuffle method.
Should I release imageMArray or set it to nil? If it should be released, should it be autoreleased?
imageMArray=[[NSMutableArray alloc] initWithArray:CategoryImages];
In the above statement, you have a memoryleak.
Instead you can have like as follows.
imageMArray = [NSMutableArray arrayWithArray:CategoryImages];
In ShuffleOnlyArray Method, return the autoreleased object.
NSMutableArray *destArray1 = [[NSMutableArray alloc] initWithCapacity: [sourceArray count]] ;
return [destArray1 autorelease];
But after you get it, retain (take the ownership) the array object.
imageMArray=[[self shuffleOnlyArray:imageMArray] retain];
Edit
In shuffle method, do as follows:
NSMutableArray *imageMArray1 = [imageMArray mutableCopy];
if( imageMArray )
{
[imageMArray release];
}
imageMArray=[[self shuffleOnlyArray:imageMArray1] retain];
[imageMArray1 release];
Edit 2:
One more solution:
Use the category to shuffle as mentioned in the SO link
No need of creating new and releasing the arrays.
1 You already have a memory leak in the following lines.
imageMArray = [[NSMutableArray alloc] initWithArray:CategoryImages];
imageMArray = [self shuffleOnlyArray:imageMArray];
In the first line you create an object with retain count 1.
Then you say that your imageMArray pointer points to other object. You should release the first object, because you louse the reference to the fist object and you can not release it after you change the reference!
2 You should not use retain because your ShuffleOnlyArray method returns a retained object.
Your factory method should return an autorelease object and the caller of the factory should decide if if will retain it or not.
Hope I was clear enough

Leak in NSMutableArray

I have been pulling out my hair trying to figure out why this is leaking. In my .h file I have a synthesized property nonatomic, retained NSMutableArray. In my viewDidLoad I declare it as:
self.tableData = [[NSMutableArray alloc] init];
[self.tableData removeAllObjects];
fillData(self.tableData);
Throughout my application, I call [self.tableData removeAllObjects] and then repopulate it with the fillData(self.tableData) function. This function fills up the data from a static C++ string set:
void fillData(NSMutableArray* list)
{
for (set<string>::const_iterator itr = sortedData.begin(); itr != sortedData.end(); ++itr){
[list addObject:[NSString stringWithFormat:#"%s", ((string)*itr).c_str()]];
}
}
In my dealloc method I do:
[self.tableData removeAllObjects], [self.tableData release], tableData = nil;
Where did I drop the ball? Instruments says it's in the [list addObject....] line.
Thanks
self.tableData = [[NSMutableArray alloc] init];
[self.tableData removeAllObjects];
fillData(self.tableData);
+1 retain for alloc, +1 retain for using the property's setter. You haven't balanced the +1 from alloc. If you are going to use the setter:
self.tableData = [NSMutableArray array];
fillData(self.tableData);
Note that removeAllObjects in that is completely pointless.
This is odd, too:
[self.tableData removeAllObjects], [self.tableData release], tableData = nil;
First, don't bother removing the objects. When the array is deallocated, it'll release all objects. Secondly, using the setter to call release and then immediately do a direct assignment is inconsistent. Either do:
self.tableData = nil;
Or:
[tableData release], tableData = nil;
(Note that the use of the , in all of this is also purely for your benefit -- it has no impact on generated code.)
Also, use stringWithUTF8String: and not stringWithFormat:.
Not sure if it's the leak, but this looks like it's a problem:
self.tableData = [[NSMutableArray alloc] init];
You say that tableData is a property that's retained. Try:
self.tableData = [NSMutableArray arrayWithCapacity:10];
That way the property retains it and the array itself is autoreleased. Your release in dealloc will bring the retain count back down to zero.
The problem is that your property is set as retain, and you set it to an already retained object.
You should do it like this:
// viewDidLoad
NSMutableArray *array = [[NSMutableArray alloc] init];
self.tableData = array;
[array release]; // this is important
// dealloc
self.tableData = nil; // will automatically release the array
In your dealloc, you use properties which retain the tableData again. That is not really what you want, so do:
[tableData release];
or
[self->tableData release]; // not necessary, but some prefer it.
or
self.tableData = nil; // property will handle release
No need to clear the tableData, no need to set anything to nil (you are deallocating, so nothing will access it anymore).

do I need to allocate and init variables with retain properties?(iphone)

#interface Approval : NSObject
{
NSMutableArray *approvalValues;
}
#property (nonatomic,retain) NSMutableArray *approvalValues;
If i do this, do I still need to call `approvalValues = [[NSMutableArray alloc] init] in the init method? I was under the impression that I had to but it is causing a leak. In the dealloc method I am releasing approvalValues
You need to alloc and init approvalValues. The problem seems to be related to the fact that you are over-retaining your object.
Your code probably looks like this:
self.approvalValues = [[NSMutableArray alloc] init];
alloc will return an object with a retainCount of 1, and when using the retain setter it will get bumped to 2. In order to solve it, you might want to autorelease the object before assigning it, making a code that looks like this:
self.approvalValues = [[[NSMutableArray alloc] init] autorelease];
This will end up with an instance variable with a retainCount of only 1, so when you dealloc the object it won't leak.
Yes you still need to alloc/init, however you only release in dealloc method.
In the init method you will often access the ivar directly and initialize it like this:
approvalValues = [[NSMutableArray alloc] init];
In the dealloc you will need a matchin release like this:
[approvalValues release];
It is often recommended to access the ivars directly in the init and dealloc method to avoid any side effects caused by setters/getters.
Throughout your class you will want to use the KVC setters/getters or dot notation to set objects like this
// Dot notation
NSMutableArray *tmpApprovalValues = [[NSMutableArray alloc] init];
self.approvalValues = tmpApprovalValues;
[tmpApprovalValues release]; tmpApprovalValues = nil;
// Call to setters/getters
NSMutableArray *tmpApprovalValues = [[NSMutableArray alloc] init];
[self setApprovalValues:tmpApprovalValues];
[tmpApprovalValues release]; tmpApprovalValues = nil;
Corrected terminology thanks to #Yuji

Memory leaks Problem in iPhone?

I want to get some memory leaks in my code, how can i fix the memory leak.
dashboard = [[NSMutableArray alloc] init];
[dashboard addObject:[[NSDictionary alloc] initWithObjectsAndKeys:#"demo_1.jpg",#"pic_source",#" Head",#"Title",nil]; // memory leaks here.
if ( theConnection ) {
receiveData = [[NSMutableData data] retain]; //memory leaks here.
}
But i have released dealloc - in[receiveData release];, but memory leaks happened. I know the retain, the count is increased, but how can i released the data properly.
Thanks!
i think your leak in the line:
[dashboard addObject:[[NSDictionary alloc] initWithObjectsAndKeys:#"demo_1.jpg",#"pic_source",#" Head",#"Title",nil];
just change it to
[dashboard addObject:[NSDictionary dictionaryWithObjectsAndKeys:#"demo_1.jpg",#"pic_source",#" Head",#"Title",nil];
addObject retains the object so you can use convenience creation methods which autorelease the object they create.
and another possible leak... if you define your receiveData as a property with retain attribute you don't need to call retain explicitely. You can call self.recieveData = [NSMutableData data]. This will retain it. Of course you will still need to release it in dealloc.
EDIT to show the code:
NSMutableArray *anArray = [[[NSMutableArray alloc] init] autorelease];
[sections setValue:anArray forKey:display_date];
dashboard addObject:[[NSDictionary alloc] initWithObjectsAndKeys:#"demo_1.jpg",#"pic_source",#" Head",#"Title",nil];
You've called init method - then you are the owner of an object. When you've put it to the array - the retain was called too. Just call autorelease to fix the leak.
receiveData = [[NSMutableData data] retain]; - if you will call release this object will be deleted when out of scope. If you will write
receiveData = [NSMutableData data];
It will be automatically deleted when out of scope
EDIT
If you are using methods with init word in them then you are the owner of such objects and they will not be deleted automatically until you'll call release method on them. If you don't want to own the object create it with some static method. For example:
NSMutableArray *array = [NSMutableArray arrayWithObjects: ... , nil];
It's the same as calling
NSMutableArray *array = [[[NSMutableArray alloc] initWithObjects: ... , nil] autorelease];
Autorelease means the object will receive a release method when out of scope - and if it was not retained will be deleted automatically