What is the differece between:
[[NSMutableArray alloc] init]
and
[NSMutableArray array]
Here in [NSMutableArray array] you don't have to release array it will be released automatically. & if you will write [NSMutableArray alloc] init] you will have to release array so [[NSMutableArray array] will be equivalent to [[[NSArray alloc] init] autorelease];
The first remains in memory until you release it, the second lasts until the end of the run loop iteration.
NSMutableArray no need to release memory and [NSMutableArray alloc] init] u must be release it.
when ARC does work, you have to release objects come from methods including init,alloc,new,copy and mutableCopy, like [NSMutableArray alloc] init]. If not, the objects will be registered to autoreleasepool, like [NSMutableArray array].
Related
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.
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];
Basically if I do (not that I want to do this, just i'm trying to understand)
array = [[NSMutableArray alloc] init];
array = [[NSMutableArray alloc] init];
array = [[NSMutableArray alloc] init];
array should now be having a retain count of 3 right?
But somehow with me it doesn't
You have allocated three different NSMutableArrays, each one with a retain count of 1.
The first two of them are leaked.
Each time your creating a new array with its retain counter.
To increase retain counter, you would have to do something like:
array = [[NSMutableArray alloc] init];
[array retain];
[array retain];
nothing -/-> [array1 - count=1] (memory leak)
nothing -/-> [array2 - count=1] (memory leak)
array ---> [array3 - count=1]
No, it won't. Actually, the three arrays are not same. All would have different references.
array = [[NSMutableArray alloc] init];
[array retain];
This will increase the retain count.
I would simply like to know how to copy a NSMutableArray so that when I change the array, my reference to it doesn't change. How can I copy an array?
There are multiple ways to do so:
NSArray *newArray = [NSMutableArray arrayWithArray:oldArray];
NSArray *newArray = [[[NSMutableArray alloc] initWithArray:oldArray] autorelease];
NSArray *newArray = [[oldArray mutableCopy] autorelease];
These will all create shallow copies, though.
(Edit: If you're working with ARC, just delete the calls to autorelease.)
For deep copies use this instead:
NSMutableArray *newArray = [[[NSMutableArray alloc] initWithArray:oldArray copyItems:YES] autorelease];
Worth noting: For obvious reasons the latter will require all your array's element objects to implement NSCopying.
I have an NSMutableArray called playlist. This is in a method called getAllPlaylists. The code is something like this:
-(NSMutableArray *)getAllPlaylists
{
//playlist is an instance variable
playlist = [[NSMutableArray alloc] init]; //memory leak here
...
//some code here which populates the playlist array
[playlist addObject: object1];
...
return playlist;
}
The array allocation step of playlist is causing a memory leak. In such a scenario where can i release this array? Or can i avoid allocation n initialization of playlist here by doing something else? Any help will be greatly appreciated!!
2 solutions:
Use autorelease:
- (NSMutableArray*)getAllPlaylists
{
playlist = [[NSMutableArray alloc] init];
...
return [playlist autorelease];
}
or instead of using [[NSMutableArray alloc] init] to create your NSMutableArray object, use [NSMutableArray array] which is equivalent to [[[NSMutableArray alloc] init] autorelease]:
- (NSMutableArray*)getAllPlaylists
{
playlist = [NSMutableArray array];
...
return playlist;
}
You should autorelease newly created objects that you want to return that are not owned by the object (local variables, not instance variables).
playlist = [[[NSMutableArray alloc] init] autorelease];
Alternatively, you can use the convenience method to do that more easily:
playlist = [NSMutableArray array];
For items the object owns (instance variables), you should make sure you release the old value first and implement a dealloc method that also releases the value.
- (NSMutableArray*)getAllPlaylists {
[playlist release];
playlist = [[NSMutableArray alloc] init];
return playlist;
}
- (void)dealloc {
[playlist release];
[super dealloc];
}
For more info, see the memory management guide.