NSMutableArray initWithCapacity method description and memory management - iphone

It's about the instance method of NSMutableArray "initWithCapacity".
From documentation, the Return Value is described as:
Return Value
An array initialized with enough memory to hold numItems objects.
The returned object might be different than the original receiver.
There seems to be a typo at "different than", my guess is it should be "different from". And also if the returned object is indeed different from the original, do we have to worry about releasing the memory associated with the original object ?
Hope that somebody knowledgable on this can help ...
http://developer.apple.com/library/mac/#documentation/cocoa/reference/foundation/Classes/NSMutableArray_Class/Reference/Reference.html#//apple_ref/occ/cl/NSMutableArray

You have created an object with alloc, and you are responsible for the memory of that object. The fact that initWithCapacity: may return a different chunk of memory than what originally came from the call to alloc does not change that.
Initializer methods in Cocoa are allowed to deallocate the instance they are passed and create a new one to be returned. In this case, it's necessary for initWithCapacity: to do so, since you're actually asking it to reserve more memory that alloc didn't know about and couldn't have allocated.
This is the reason that alloc and init... should always be paired: [[NSMutableArray alloc] initWithCapacity:10]
Regarding initWithCapacity: specifically, bbum (who knows of what he speaks -- Apple engineer) says that it's usually unecessary. It does not preclude you from expanding the array past the specified size. All it does is potentially allow the array to do some initial optimization*; unless you've measured and it makes a significant difference, it's probably not necessary.
*See Objective-c NSArray init versus initWithCapacity:0

Any time you use a method that contains the word alloc then you are responsible for releasing the memory. For example if you did the following
NSMutableArray *myArray = [[NSMutableArray alloc] initWithCapacity:10];
//Store data into the array here
//Once done you need to release the array
[myArray release];
--Editied post because I meant to type alloc and used init instead.

Related

objective-c: when to autorelease an nsnumber object when not using alloc

I noticed that my program was crashing because it was running out of memory. I figured out that this was happening because of this code segment:
DataSet *tempSet = [[DataSet alloc] init];
tempSet.rightFoot = [NSNumber numberWithDouble:temp1];
tempSet.leftFoot = [NSNumber numberWithDouble:temp2];
[footData addObject:tempSet]; //add dataSet object to the array
[tempSet release];
I read some tutorials about memory management online and was able to figure out that I needed to do this: (notice the added "autoreleases")
DataSet *tempSet = [[DataSet alloc] init];
tempSet.rightFoot = [[NSNumber numberWithDouble:temp1] autorelease];
tempSet.leftFoot = [[NSNumber numberWithDouble:temp2] autorelease];
[footData addObject:tempSet]; //add dataSet object to the array
[tempSet release];
I am still confused about why I had to do this. I did not use alloc, new or copy when creating the numberWithDouble.
Does this mean that I would need to add autorelease in this situation as well?:
[subset addObject:[NSNumber numberWithDouble:temp]];
What about this situation?:
tempSet.rightFoot = [NSString stringWithString:#"temp"];
I appreciate any help.
+numberWithDouble
is called a convenience method. Meaning, it replaces the little section of code that would look like this:
[[[NSNumber alloc]initWithDouble:double]autorelease];
Most (if not all) convenience methods are auto release by default, so the OP code with the autoreleases is incorrect, as it drops the retain count to -1.
The equals sign however is equivalent to
[self setRightFoot:[[[NSString alloc]initWithString]autorelease]];
which increments rightFoot's retain count and requires it to be released elsewhere.
as for the -addObject code, it returns void, so it does not in fact increment the receiver's retain count, and requires no release of the receiver. The object in the array should already be released by the convenience method for later, which doesn't matter because the array is now holding "copy" of it.
This is not an answer (I just do not know how to comment -- I only see "share, edit, flag"), but just a few info about Memory Management in iOS:
1. Don't release objects that you do not own.. ---> owned objects are usually the ones you "alloc", "new", "copy." //And probably the one in your #property wherein you "retain" an object.
2. when you "autorelease" an object, don't "release" it afterwards, because that would mean you're releasing the same object twice.
But there's ARC already, so you better upgrade your Xcode to avoid overreleasing objects / memory leaks (for not releasing objects)..
If there's something wrong or inappropriate with the one I put here, please edit. :)

What is the difference between these two ways of allocating memory in Objective-C?

I am confused about the proper means of allocating memory in Objective-C. Suppose I have an NSMutableDictionary. There are two ways I can initialize it:
NSMutableDictionary *alpha = [[NSMutableDictionary alloc] init];
or
NSMutableDictionary *alpha = [NSMutableDictionary dictionary];
What is the difference between them? I know the first allocates memory for alpha, but what about the second?
Which of these is recommended as the best practice for allocating memory?
[NSMutableDictionary dictionary];
is exactly the same thing as:
[[[NSMutableDictionary alloc] init] autorelease];
It just saves you some typing. It doesn't matter which one you use, as long as you know the difference between a retained object and an autoreleased one. If you're using ARC, then you don't even need to know that.
The convention is:
If you see init, new or copy: it's a retained object.
If the method name starts with the class name (sans the framework prefix), it's an autoreleased object.
[NSMutableDictionary dictionary] is a class method on the NSMutableDictionary class. It contains the calls to alloc and init, just as you would do them manually. Due to this being a very commonly used class, its author included this so called "factory method" to make life easier for users of his/her class.
See http://en.wikipedia.org/wiki/Factory_method_pattern for more details on this pattern.
As for which is good practice, IMHO you should use the factory method. It makes your own code more readable and saves you typing. Moreover - although I am not sure if this is the case with NSMutableDictionary - using the factory method makes maintenance easier for both its developers and yourself, because they are e. g. free to change the concrete subclass implementation you will receive from the factory, without having you change your application code.
As correctly pointed out it the comments, factory methods like this return autoreleased instances of objects, so if you only use them locally in a method, there is no need to worry about them from a memory management point of view. For more details on memory management, autorelease and the new ARC runtime with automatic reference counting, you should deep dive into Apple's documentation on the topic, if you haven't already.
Both line will allocate memory for alpha, difference is that second alpha is autorelease object.

Correct use of autorelease

I am trying to understand why my application crashes and I am going through my code. I am pretty sure that this is a valid use of autorelease:
(part of the code)
- (NSArray *)allQuestionsFromCategories:(NSArray *)categories {
...
NSMutableArray *ids = [[[NSMutableArray alloc] init] autorelease];
while (sqlite3_step(statement) == SQLITE_ROW) {
[ids addObject:[NSNumber numberWithInt:sqlite3_column_int(statement, 0)]];
}
return [NSArray arrayWithArray:ids];
}
Is this valid? The NSArray arrayWithArray returns an autorelease object doesn't it? I also have some difficulties in understanding the scope of autoreleased objects. Would the autoreleased object (if it is in this case) be retained by the pool through out the method that invoked the method that this code is a part of?
- (void)codeThatInvokesTheCodeAbove {
NSArray *array = [self.dao allQuestionsFromCategories];
...
}
Would the array returned be valid in the whole codeThatInvokesTheCodeAbove method without retaining it? And if it was, would it be valid even longer?
Got some issues understanding the scope of it, and when I should retain an autorelease object.
That is valid, but -- really -- you can just skip the [NSArray arrayWithArray:ids]; entirely as there is no need to create a new array.
An autoreleased object is valid until the autorelease pool is drained, which typically happens once per pass through a run loop (or "periodically, but never while your block is executing" when enqueuing stuff via GCD).
The documentation explains it all better than I.
There is no need to create an immutable array because the return will effectively "up cast" the NSMutableArray to NSArray. While this is meaningless at run time, it means that the caller cannot compile a call to a mutating method of the returned value without using a cast to avoid the warning. Casting to avoid warnings in this context is the epitome of evil and no competent developer would do that.
If it were an instance variable being returned then, yes, creating an immutable copy is critical to avoid subsequent mutations "escaping" unexpectedly.
Have you read the memory management documentation? Specifically, the part about autorelease pools? It makes it quite clear how autorelease works. I hate to paraphrase a definitive work.
[NSArray arrayWithArray:] returns an autoreleased object. If you want codeThatInvokesTheCodeAbove to take ownership of the array, you should call retain on it (and rename codeThatInvokesTheCodeAbove according to apple's guidelines). Otherwise, if you don't care that ownership of the object is ambiguous then your code is okay.
In other words, [NSArray arrayWithArray:] returns an array that you don't own, but you have access to it for at least this run cycle. Therefore, codeThatInvokesTheCodeAbove will have access to it for at least this run cycle. Ownership is not clear, since nobody called alloc, copy, new, or mutableCopy or retain. It is implied that NSArray called autorelease before returning the new array, thus relinquishing ownership.
My information comes from http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html%23//apple_ref/doc/uid/20000994-BAJHFBGH.
So, to answer your question, yes your posted code is valid. Whether it's correct depends on what it is you are trying to accomplish.
Autoreleased object are objects that are marked as to be release later.
There is a very particular object that is automatically created by UIApplicationMain: an UIRunLoop.
Imagine it like a while structure, it cycle until application is terminate, it receives every event and properly resend it to your interested classes, for example. Just before UIApplicationMain there is a command to create an NSAutoreleasePool that, once the NSRunLoop is ready, attach to it. When you send an -autorelease command to an object, the NSAutoreleasePool will remember to release it when is released itself. It's dangerous to use it many times in platforms that has less memory (iOS devices), because objects aren't released when you send an -autorelease command but when the NSAutoreleasePool is drained (when app releases it).
If you want to free the non-mutable list before you return, you can use something like this:
- (NSArray *)allQuestionsFromCategories:(NSArray *)categories {
...
NSArray* result;
NSMutableArray *ids = [[NSMutableArray alloc] init]; // AUTORELEASE REMOVED FROM HERE
while (sqlite3_step(statement) == SQLITE_ROW) {
[ids addObject:[NSNumber numberWithInt:sqlite3_column_int(statement, 0)]];
}
result = [NSArray arrayWithArray:ids]; // COPY LIST BEFORE IT IS FREED.
[ids release]; // MUTABLE LIST FREES _NOW_
return result; // NONMUTABLE COPY IS RETURNED
}
It is not worth doing this unless your mutable array is likely to sometimes use a lot of memory.

releasing variables to save memory

I have a beginner's question about releasing variables and not wasting memory...
I don't quite understand when to release variables. I understand that I should always do this if I have assigned them in my header file (in my #interface section and my #property commands). I release them in my -(void)dealloc function.
However, what am I supposed to do with variables that I happen to use in some of my methods, e.g.:
for (int temp = 0; temp < 3; temp++) {
// do something...
}
[temp release];
This is obviously wrong (at least xCode tells me so), as 'temp' is undeclared. But why? I've declared it as an int and temp thus takes up space in my memory, I'm sure. How do I tell the program to free up the space temp has taken after I don't need it anymore? I'm sure this is obvious, but I simply don't get it.
I'd be very happy for any suggestions for a beginner of how not to be a memory pig and to have 'memory leaking' everywhere in my apps...
You declared it as an int in the scope of the loop. Once the loop is done, it goes out of scope.
Also, you can not release an int, which is a primitive type. You can only release a subclass of NSObject. A good rule of thumb is that you eventually have to release anything that you called alloc or retain on.
Edit: For your edification, memory management only applies to objects allocated from the heap. That would be NSObjects obtained via "alloc" or must C-level memory allocated with something like "malloc()". Declaring a variable like "int x" is called an "auto" variable in that is is created on the stack and will AUTOmatically disappear then that block ends (the end of a "block" being the end of the function or perhaps the end of a {} pair or even the end of a for/if/while block.
Since Objective-C is basically just a special version of C (with messages), it does not create permanent objects unless you explicitly tell it to. This is different form languages like Python or Javascript.
You only need to release objects, and temp is an int, not an object.
As far as when to release objects, Apple's docs explain that better than I can: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
You do only release objects, and not primitive types. For example you create an array with
NSArray *myArray = [[NSArray alloc] init];
This initialization allocated memory which you have to free after your done using your array, it's your responsibility, else there will be memory leaks. You can do that in the dealloc section of a controller, or at the end of a method, or even after you've enumerated through the array and no longer need it.
If you create instances of objects with other methods than alloc, copy or new(rarely used) you have to release them. If you call retain yourself on an object you have to release it as well.
Please refer to apples memory management rules, which have been posted earlier.
There are two ways to store information in RAM in C and c like things, primitives which are allocated automatically by the compiler, and memory chunks allocated by you in your program.
Variables allocated for you by the compiler are called "automatics" and can be marked by the essentially unused (because it is the default) "auto" keyword. Automatics are bound to the scope in which they are declared and go away when it ends. Regular variables, like "int x" are automatic.
Notably, pointers are typically automatic. However, the things they point to are not. Those would be the thing you asked to be allocated.
In objective-c, things are allocated with the alloc message. However, sometimes a class will call this for you, so you might not see it. To help make it clear what you should do, there is a tradition: If you get an object where you alloc'ed it, got it from a class method with the word "copy" in the method name, or sent it a "retain" message, then you own a share of it, and it won't go away until you send it a release message.
If you didn't get the object through one of those means, you must not release it, because you don't have a share in it.
So, in summary: regular variables (int, short, char, double, float, long) are automatic, no need to allocate it. Pointers are also automatic, however, the things they are pointing to are not. In obj-c, you own a share if you alloc'ed it, copy'ed it, or sent it a retain message.
You can't release an integer...
Release works only with instance of Objective-C classes.
Variables such as integers are placed on the stack, and they does not persist after a function/method call, unless allocated explicitely.
You only release objects. If you use the alloc, init procedure to create an object you must release it. If you retain an object you must release it. If you use a method that has the word "create" in it, you must release it. Anything else, the system will handle for you.
Primitives do not need to be released, only objects.
Biggest thing to keep in mind is that whenever you "alloc" or "retain" an object, put a corresponding "release" or "autorelease".
you see an error on the line [temp release]; because temp is not in scope. temp will not be seen outside of the for loop you created.
you do not need to clean up the memory of temp, since you have not claimed ownership of it(see Memory Management Rules): http://developer.apple.com/library/ios/#documentation/general/conceptual/DevPedia-CocoaCore/MemoryManagement.html
examples of objects where you do not need to release/manage memory:
NSArray *myArray = [NSArray array];
NSNumber *myNumber = [NSNumber numberWithInt:5];
NSString *myString = #"Hello World";
NSInteger i = 5;
int x = 2;
examples of objects where you do need to release/manage memory:
NSArray *myArray = [[NSArray alloc] initWithObjects:#"Hello", #"World", nil];
NSNumber *myNumber = [[NSNumber alloc] initWithInt:5];
NSString *myString = [[NSString alloc] initWithString:#"Hello World"];
-
typically, when your completely done using an object you own, you clean up its memory
see apple's docs for explanations on properties: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW1
setting a property with assign or readonly: you should not worry about releasing its memory, as you don't own it
property with retain or copy: you claim ownership of the object and need to release it at some point
this answer won't answer/solve all memory management questions/concerns, but it may shove you in the right direction

Is release without prior retain dangerous?

I have some code which I think has extra release statements.
Is the code incorrect?
What is the end result?
I don't understand memory management well yet - even after reading lots of articles and stackoverflow answers. Thanks for straightening me out.
Update: The attached snippet works fine, but other code has the over-release problem
NSMutableArray *points = [NSMutableArray new];
for (Segment *s in currentWorkout.segments) {
[points addObjectsFromArray:[s.track locationPoints]];
}
[routeMap update:points];
[points release];
Your code is correct, but inadvisable. new acts as an implied alloc, which creates the object with a retain count of 1.
I think the last time I used new was in 1992; it's not wrong, but alloc/init is considered better practice, because it is clearer what you are doing. Please read Apple's guide to memory management, it is a comprehensive summary of the situation.
No messages can safely be sent to a deallocated object. Once an object has been released a sufficient number of times, it's deallocated. Any further messages sent to that object are going to an object that isn't there anymore. The precise result isn't completely predictable, but it usually ends in a crash. If you're less lucky, it could end in much stranger ways — for example, you could theoretically wind up with an Object A getting dealloced early and Object B allocated in the same memory location, then Object B receiving messages meant for Object A that Object B does understand but isn't supposed to receive at that time.
Basically, follow the rules. Think of it in terms of ownership. If you've claimed ownership, you need to release that ownership. If you don't own the object, you must not release it.
Take a look at this article online: http://weblog.bignerdranch.com/?p=2 .
It seems to imply that calls to release without a corresponding preior call to retain will result in a BAD_ACCESS error.
A short answer is, if you increasing the retain count of an object and you no longer are using it you should release it, otherwise you shouldnt...
So when ever you do a [objectName alloc] you are increasing the count by 1, when you use such methods as [NSString stringWithString:] these methods return an autoreleased object so you dont need to release it...if you instead did something like [[NSString stringWithString:]retain] then you are increasing the strings retain count and you should release it after you are done using it.
Im not too sure if new increases the reference count (i suspect that it would), you can always check your retain count by doing [object retainCount]... though note that even if the retain count is greater than 0, it does not mean you need to release the object, because some other class might have a reference to the object and therefore has its retain count increased by one and its the responsibility of the other class holding the reference to release it.
Hope this helps
you should use:
NSMutableArray *points = [[NSMutableArray alloc] init];
[...]
[routeMap update:points]; //if routemap stores the points, it will need it's own release retain
[points release]; //if there is a retain in the method above, reference will not be cleared
if unsure, use the build->analyze command, it will search your code for leaked references
you can get the official memory management guide from https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html