Block Storage Area-how to verify whether a block is on the stack or on the stack
The block storage area requires three terms: ● _ NSConcretStackBlock ● _ NSConcretGlobalBlock
● _ NSConcretMallocBlock
The three block storage methods are described as follows: Stack, global, and heap. [Point 1] The block defined outside the function is global. In addition, if the block inside the function does not capture any automatic variables, it is also global. For example, the following code:
typedef int (^blk_t)(int);for(...){ blk_t blk = ^(int count) {return count;};}
Although this block is in a loop, the blk address remains unchanged. This block is in the global segment. [Point 2] One case cannot be compiled without ARC: typedef int (^ blk_t) (int); blk_t func (int rate) {return ^ (int count) {return rate * count ;}} this is because the block captures the rate automatic variable on the stack. At this time, the rate has become a struct, and the block has a pointer to this struct. That is, if block is returned, it is the pointer to the local variable. This point is precisely determined by the compiler. This problem is not found in ARC because ARC uses autorelease. [Point 3] Sometimes we need to call the block copy function to copy the block to the stack. See the following code:
-(id) getBlockArray{ int val =10; return [[NSArray alloc]initWithObjects: ^{NSLog(@"blk0:%d",val);}, ^{NSLog(@"blk1:%d",val);},nil];}id obj = getBlockArray();typedef void (^blk_t)(void);blk_t blk = (blk_t){obj objectAtIndex:0};blk();
This code will be abnormal in the last line of blk (), because the block in the array is on the stack. Because val is on the stack. The solution is to call the copy method. [Point 4] No matter where the block is configured, copying using the copy method will not cause any problems. In the ARC environment, if you are not sure whether to copy the block, just copy it. ARC will clean the battlefield. NOTE: If copy is called on the stack, copy is copied to the stack, and copy is called on the global block. The block reference count is increased when copy is called on the stack.
I used Xcode 5.1.1 iOS sdk 7.1 to compile and found that the Code int val below must be on the stack, not as described in Objective-C advanced programming, I saved the val address to check whether the block changes before and after calling. The output consistency is on the stack, and the inconsistency is on the stack.
Typedef int (^ blkt1) (void);-(void) stackOrHeap {_ block int val = 10; int * valPtr = & val; // use the int pointer, to check whether the block is on the stack or on the stack, blkt1 s =^{ NSLog (@ "val_block = % d", ++ val); return val ;}; s (); NSLog (@ "valPointer = % d", * valPtr );}
Under ARC, >>>>>>>>>>> the block is directly generated to the stack. Check log: val_block = 11 valPointer = 10 under non-ARC >>>>>>>> the block is still on the stack. View log: val_block = 11 valPointer = 11
The result after the copy operation is called:
-(Void) stackOrHeap {_ block int val = 10; int * valPtr = & val; // use the int pointer to check whether the block is on the stack, or heap blkt1 s = ^ {NSLog (@ "val_block = % d", ++ val); return val ;}; blkt1 h = [s copy]; h (); NSLog (@ "valPointer = % d", * valPtr );}
---------------- Under ARC >>>>>>>>>>>>> no effect. Val_block = 11 valPointer = 10
---------------- Under non-ARC >>>>>>>>>> it is indeed copied to the stack. Val_block = 11 valPointer = 10
Use this table to indicate/* When the block captures automatic variables -------------------------------------------------------------------- | where block stay | ARC | non-ARC | callback -------------------------------------------------------------------
| Copy | heap | ------------------------------------------------------------------ | no copy | heap | stack | Snapshot ------------------------------------------------------------------
*/For details, see click to open the link.