Block Memory Allocation in iOS

Introduction I originally intended to write a quick summary of Block memory management, but the topic turned out to be a much deeper rabbit hole than expected. Block Types A Block is itself an object. In most cases, Blocks are allocated on the stack. A Block is only allocated in the global data segment when it is defined as a global variable or when no automatic variables are referenced inside the Block (corresponding to the heap and text segment below). variables are also allocated on the stack. Under ARC, the compiler automatically handles most Block memory management for us, but when a Block is passed as a method parameter, the compiler does not do this automatically — you must manually copy the Block object. Fortunately, most Cocoa framework APIs whose names contain , as well as GCD APIs, already perform a copy internally, so you don't need to handle that yourself. Outside of those cases, however, manual intervention is required. Based on their location in memory, Blocks fall into three types: , , and . NSGlobalBlock is similar to a regular function and lives in the text segment. It contains no references to any external variables. , , and operations on an all have no effect. NSStackBlock lives on the stack. It becomes invalid after the function returns because it references external variables. Under MRC: A stack Block is reclaimed when the function exits. Calling the Block after that causes a crash: The Block added inside is a stack Block; calling it inside will crash the program. The fix is to copy the Block to the heap first: Under ARC: Under ARC, the printed type is not . Many people assume that under ARC there are only and , but that is incorrect. Under ARC, the generated Block is still an ; it is just that when assigned to a strong object, the system automatically copies it: NSMallocBlock lives on the heap. If an needs to be used outside its scope, you must manually copy it to the heap under MRC. supports and , which increment and decrement the retain count respectively. does not create a new object — it simply adds a reference, similar to . Under ARC, the Block is automatically copied to the heap, so manual management is unnecessary. Use ARC whenever possible. Summary of copy, retain, and release on Blocks - is equivalent to ; is equivalent to . - For a Block, , , and do not change the ; is always 1. - : , , and are all no-ops. - : and are no-ops. It is crucial to know that after a function returns, an 's memory is reclaimed. Even will not help. A common mistake is (note: under ARC this is not a concern because ARC copies stack Blocks to the heap by default). After the function returns, the retrieved from will be a dangling pointer. The correct approach is to first copy it to the heap: . on an creates a new . - supports and ; although always shows 1, the memory manager still increments and decrements the count internally. does not create a new object — it just adds a reference, similar to . Avoid using on a Block when possible. Block Access to Different Variable Types Local Variables Read-only inside a Block. When the Block is defined, the variable's value is copied and treated as a constant inside the Block. Therefore, even if the variable's value changes outside the Block, it does not affect the value inside the Block. Static Variables and Global Variables If in the example above is changed to a global or static variable, the Block can both read and write it. Because global and static variables have fixed addresses in memory, the Block reads the variable's current value directly from that address rather than a copy made at definition time. The output is , showing that changes to outside the Block affect its value inside the Block, and likewise that changes to inside the Block affect its value outside the Block. Block Variables Variables modified with are called Block variables. For primitive types, variables behave like global or static variables. When a Block is used by another Block, and that outer Block is copied to the heap, the inner Block is also copied. However, a Block passed as a parameter is not copied. Objective-C Objects Unlike primitive types, Blocks affect the retain count of Objective-C objects. Under ARC, be careful about retain cycles. References: Differences Between Blocks Under ARC and Non-ARC Using Blocks Correctly to Avoid Retain Cycles and Crashes Block Memory Management