The short answer is that objects are always allocated on the heap, not on the stack.
This is not the whole story. In Objective-C, blocks are also full Objective-C objects. They are peculiar in that they are sometimes on the stack. In particular, blocks created with block literal syntax that reference the surrounding volume are on the stack. You can even see this if you check out their class, which will be the (private) NSStackBlock . If you copy them, with Block_copy() or -copy , the resulting copy will be on the heap ( NSMallocBlock ).
One consequence of this is that blocks allocated by stacks are valid only until the end of the area in which they were created. Prior to ARC (and IIRC in the early version of ARC), this meant that you had to copy the blocks that you wanted to live outside of your creation area so that they were on the heap. ARC handles this for you in most cases now, and also means that a block is on the stack or a lot more difficult to predict.
This little test program shows this (compile with ARC disabled):
#import <Foundation/Foundation.h> // Compile this without ARC. int main(int argc, char *argv[]) { @autoreleasepool { NSMutableString *string = [NSMutableString stringWithString:@"foo"]; void(^stackBlock)() = ^{ [string setString:@"bar"]; }; NSLog(@"stackBlock class: %@", NSStringFromClass([stackBlock class])); void(^heapBlock)() = [[stackBlock copy] autorelease]; NSLog(@"heapBlock class: %@", NSStringFromClass([heapBlock class])); } }
Output:
stackBlock class: __NSStackBlock__ heapBlock class: __NSMallocBlock__
(To be clear, you should not use validation for NSStackBlock / NSMallocBlock in real code. These are private implementation detail classes. This code is for demonstration purposes only.)
source share