Objective C: Memory Allocation on stack vs. heap - objective-c

I am somewhat confused about when things are allocated on the heap (and I need to release them) and when they are allocated on the stack (and I don't need to relese them).
Is there a rule of thumb?
I think in C++ the rule of thumb is that if you use the new keyword they are on the heap. What is the rule with objective c? How can I tell when something is allocated on the stack?
Will this line of code be allocated on the stack?
NSString *user = #"DEFAULT";

Objective-C is easy in this regard.
All Objective-C Objects Are Always Allocated On The Heap.
Or, at the least, should be treated as if they are on the heap.
For:
NSString *user = #"DEFAULT";
The string object is not technically in the heap, but might as well be. Namely, it is generated by the compiler and is a part of your app's binary. It doesn't need to be retained and released because the class (NSCFConstantString, IIRC) overrides retain/release/autorelease to effectively do nothing.
As for when you do and don't release objects, you should read (and re-read) the Objective-C memory management guide.
(There is one other exception, but it is a rather esoteric detail; blocks start on the stack and you can Block_copy() them to the heap. Blocks also happen to be Objective-C objects, but that is rarely exposed in use.)

In Objective-C, it's easy: all objects are allocated on the heap.
The rule is, if you call a method with alloc or new or copy in the name (or you call retain), you own that object, and you must release it at some point later when you are done with it. There has been plenty written on the subject.
The example you give is a special case: that's a static string, I believe it is actually located in the program's data segment (on the heap), but it's static so you don't need to worry about releasing it.

There are no stack allocations of objects in Objective-C (Blocks are a different case that I'm not going to get into here)
NSString *user = #"DEFAULT";
That allocates a NSConstantString object in constant memory, not on the stack.

In Objective-C (and many other languages), an object is simply a contiguous blob of memory with a particular layout. Objects are usually created on the heap. The storage for the object pointer variable itself is on the stack
but the object it points to is in the heap.

Related

Dealloc and ARC

I read that when using ARC in Objective-C programming in Xcode the dealloc method is called automatically by the compiler. Under what circumstances is it called?
In order to avoid having too many variable names, when I need to repeatedly use the same classes to do multiple operations (and resetting the variable each time) I often declare the variables, set them to nil, and then assign values to them as I go. This ends up looking like this:
MyClass mc;
mc = [[MyClass alloc] init];
[mc doThis:someOption]
mc = [[MyClass alloc] init];
[mc doThis:someOtherOption];
//etc...
The method name alloc is short for "allocate" because it is the method where memory is allocated to the variable. Does the compiler automatically release the memory for sc every time I assign it a new value? I plan on using this method in a project of mine, and I don't want a lot of memory being allocated with all the times I call alloc to assign a new value to mc.
The compiler never calls dealloc. The compiler inserts retain, release and autorelease (more efficient equivalents, really) as necessary to follow the memory management rules.
When the compiler inserts said calls is up to the compiler and the details will change across different compiler versions and different optimization levels.
I.e. you shouldn't need to worry about it in general.
However, autorelease pressure can still be an issue, as can retain cycles. Thus, you should definitely poke about your app with the Allocations Instrument to both measure the high-water mark and make sure your app isn't leaking memory over time.
I read that when using ARC in Objective-C programming in Xcode the dealloc method is called automatically
In Objective-C, you never call -dealloc directly whether or not you're using ARC.
Under what circumstances is it called?
-dealloc is called when an object's retain count drops to zero. That is, it's called when all the objects that had previously asserted "ownership" of the object (by calling +alloc or -retain or -copy or +new) have renounced that ownership (by calling -release or -autorelease).
Does the compiler automatically release the memory for sc every time I assign it a new value?
If you're using ARC (and you should be), the compiler will insert appropriate calls to -retain, -release, etc. so that memory is managed appropriately. That said, you still need to understand how memory management works, and you should be familiar with the material in Advanced Memory Management Programming Guide.
Under ARC, your variable mc will hold a strong reference to only one instance of MyClass at a time, so when you allocate the second one and assign it to the variable, the first one should be getting deallocated, assuming your doThis: method doesn't do something that will create another strong reference to that instance, or that you're not doing anything else in your code that you've omitted that will keep a strong reference.
That being said, it would be a good idea for you to run your app with Instruments to see how much memory your app uses during this. Your instances shouldn't be getting autoreleased, so you shouldn't have to worry about them remaining around until the autorelease pool is drained, but I don't know what you might being doing when you init an instance of the class, or what you might be doing in your doThis: method, so if you're concerned, it's always a good idea to profile it with Instruments for memory allocations and leaks.

Storing Blocks in an Array

In Objective-C, I know that blocks are considered objects, so I was wondering if it was possible to store them in an array. This begs the question, are blocks first class objects or are they just treated like objects for the sake of passing them between objects? If they are first class objects, then shouldn't they be storable in arrays?
EDIT: Without going into too much detail, under ARC, you can now add blocks to collections like any other object (see discussion).
I've left the original answer intact below, since it contains some interesting technical details.
This begs the question, are blocks first class objects or are they
just treated like objects for the sake of passing them between
objects? If they are first class objects, then shouldn't they be
storable in arrays?
Blocks are Objective-C objects that very much behave like every other NSObject, with a couple of key differences:
Blocks are always generated by the compiler. They are effectively "alloc/init"ed at runtime as execution passes over the blocks declaration.
Blocks are initially created on the stack. Block_copy() or the copy method must be used to move the Block to the heap if the Block is to outlive the current scope (see ARC point below).
Blocks don't really have a callable API beyond memory management.
To put a Block into a Collection, it must first be copied. Always. Including under ARC. (See comments.) If you don't, there is risk that the stack allocated Block will be autoreleased and your app will later crash.
Copying a stack based block will copy all of the captured state, too. If you are making multiple copies of a block, it is more efficient to copy it once, then copy the copy (because copying the copy just bumps the retain count since Blocks are immutable).
Under ARC, returning a Block from a method or function "just works"; it'll be automatically copied to the heap and the return will effectively be an autoreleased Block (the compiler may optimize away the autorelease in certain circumstances). Even with ARC, you still need to copy the block before sticking it into a collection.
I've written a couple of blog posts both providing an introduction to blocks and some tips and tricks. You might find them interesting.
And, yes, adding 'em to dictionaries is quite useful. I've written a couple of bits of code where I dropped blocks into dictionaries as command handlers where the key was the command name. Very handy.
Yes, blocks are indeed objects, and you can put them in arrays:
NSMutableArray *arr = [NSMutableArray new];
[arr addObject:^(){NSLog(#"my block");}];
void (^ myblock)() = [arr objectAtIndex:0];
myblock();
this will put the "my block" in the console.

Can we release some memory in Objective-c that a variable does not own but points to?

I have some code like this:
NSObject *var1 = [[NSObject alloc] init];
NSObject *var2 = var1;
[var2 release];
var1 = nil;
Is this correct or is this a memory leak?
As far as I know only var1 can release the memory alloc-inited in the first line, as per the Object Ownership policy
Your code will release the memory, because there is a single alloc, and a single release - the amount of pointers to the object is not a factor.
Ownership is a concept that the Object Ownership policy talks about because if you follow the guidelines it makes it easier to manage and ultimately prevent problems relating to releasing things you shouldn't release (or not releasing things you should).
Your code is all right and doesn't leak. But it seems like you don’t really understand pointers. A pointer can not own another object, it is just a reference that tells the computer which object is being accessed. In the reference-counted memory model of Cocoa it doesn’t matter at all how many pointers point to a single object.
You really should learn C (especially about pointers) before you try to learn Objective-C.
Your example will not result in a memory leak as var1 and var2 point to the same object in memory—thus the alloc call has a matching release. If the NSObject was retained as it was assigned to var2 however, there would be a memory leak as there would be no matching release.
When the memory management guide talks about the concept of ownership, it doesn't mean that a variable (e.g. var1) owns an object; it's more about what "scope" owns it (e.g. a class or method). In your example, the method containing those statements would be responsible for releasing the object.
It's the object that keeps a reference count, not the pointer to the object. If you have a dozen pointers to an object, you could use any one of them to release the object because they're all pointing to the same object. However, it's a lot easier to follow your code and make sure that you don't have memory management problems if you don't play those sorts of games.

Objective-C memory management: do you need to release string literals?

do you need to release something very simple this?
NSString *a = #"Hello";
//[a release]; ?
I come from a Java/C# world, and am confused about when things should be released/retained.
No. You only need to release objects you init/alloc yourself or your instance variables in your class dealloc method.
No, you do not need to release a constant NSString, though it doesn't cause any problems if you do. Constant strings are special case of the memory management system. Since their content is known at compile time, it is statically defined in the application binary itself, so it never has to be allocated or freed at runtime. For that reason, its retain and release methods are noops.
This is only true for constant NSStrings (strings that start with #), and their toll free bridged cousin, constant CFStrings (defined using the CFSTR() macro).

Objective-C: Setting autoreleased objects to nil

Is it safe to set an autoreleased object to nil? I know I don't need to release an autoreleased object but if I want the object to be released immediately to minimize memory use, can I set the object to nil?.
I may have read this somewhere a while back, but I can't remember where and I want to make sure that it is safe to do that.
I think you're missing something pretty fundamental. Setting an object to nil does nothing for you in terms of memory management. Here's what's going on:alt text http://gallery.me.com/davedelong/100084/Pointers1/web.png?ver=12783505480001
In this image, you have the stack (where your local variables live; it's more or less synonymous to where you currently are in your code while executing). If you declare something like int bar = 42;, then bar lives on the stack. On the right you have the heap. This is global memory space that belongs to your application. The heap was invented to solve the problem of scope: how to make useful information live beyond the scope of the current function (or method). When we malloc space, we are assigned a slot of memory on the heap. When you alloc/init an object, that object lives on the heap. In Objective-C, all objects live on the heap.* So let's consider this line:
MyObject * foo = [[MyObject alloc] init];
We really have 2 things going on. The first is that we have allocated (alloc) a new chunk of space on the heap that's large enough to hold a MyObject structure. Then we've taken the location of that chunk o' memory and assigned it into a local variable called foo. In the image above, the reddish circle on the left is foo, and the reddish blob on the right is the actual MyObject (along with all of its data). Make sense so far?
Here's what happens when you "set an object to nil" (foo = nil;)
alt text http://gallery.me.com/davedelong/100084/Pointers2/web.png?ver=12783505490001
You'll see that the object still lives on the heap. In fact the only thing that has changed is that your local variable foo no longer points to the chunk of memory on the heap. It points to 0 (nil, NULL, whatever you want to call it), which is how we indicate that "this doesn't point to anything relevant any more".
In a nutshell: setting a variable to nil has nothing to do with memory management. If you want to get rid of an object immediately, then use release and not autorelease. However, even then that's not a guaranteed "destroy immediately", since something else might be retaining the object (which is the whole point of using the retain-release memory management model).
Beyond this, once you're done with an object (and after you've invoked either release or autorelease), it's still a good idea to set the variable to nil, just to avoid potential problems. In Objective-C we can safe send messages to nil without things blowing up in our faces (unlike Java). However, if you don't "nil out" a variable, bad things can happen. Let's say foo is pointing to a MyObject instance, and then the MyObject instance is destroyed (you released it, but didn't set it to nil). If you try to invoke a method on foo again, your app will crash. If you do set foo to nil, then your app will continue on its merry way. It might not do what you were hoping, but that's a different problem entirely.
Welcome to the wonderful world of Objective-C memory management.
* except for local blocks, but then only until they're copied. There are some other caveats to this as well, but that's getting into the arcane.
Yes, this is good practice as demonstrates that object is unused - i.e. no referenced data.
For what it's worth, you'll see it a lot in the sample code from Apple as well.