Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Under ARC, are Blocks automatically copied when assigned to an ivar directly?

Assume the following code under ARC,

typedef void (^MyResponseHandler) (NSError *error);
@interface MyClass : NSObject
{
    MyResponseHandler _ivarResponseHandler;
}

- (void)myMethod:(MyResponseHandler)responseHandler
{
    _ivarResponseHandler = responseHandler;
    ...
}

Question: Is the block automatically copied to the heap when assigned to the ivar?

My previous question implied that it is copied when assigned through a @property. But, today I used the above code and received an EXC_BAD_ACCESS that was fixed by changing to

_ivarResponseHandler = [responseHandler copy].

like image 547
bearMountain Avatar asked May 04 '12 17:05

bearMountain


2 Answers

Edit: My previous answer was likely wrong.

Some selected excerpts from the ARC docs say:

3. Retainable object pointers

A retainable object pointer (or retainable pointer) is a value of a retainable object pointer type (retainable type). There are three kinds of retainable object pointer types:

  • block pointers (formed by applying the caret (^) declarator sigil to a function type)

4.2. Semantics

Assignment occurs when evaluating an assignment operator. The semantics vary based on the qualification:

  • For __strong objects, the new pointee is first retained; second, the lvalue is loaded with primitive semantics; third, the new pointee is stored into the lvalue with primitive semantics; and finally, the old pointee is released. This is not performed atomically; external synchronization must be used to make this safe in the face of concurrent loads and stores.

4.4.1. Objects

If an object is declared with retainable object owner type, but without an explicit ownership qualifier, its type is implicitly adjusted to have __strong qualification.

7.5. Blocks

With the exception of retains done as part of initializing a __strong parameter variable or reading a __weak variable, whenever these semantics call for retaining a value of block-pointer type, it has the effect of a Block_copy. The optimizer may remove such copies when it sees that the result is used only as an argument to a call.

So I think the answer is maybe, depending on the optimizer.

like image 105
sbooth Avatar answered Sep 25 '22 17:09

sbooth


Your problem and solution indicate that my answer to your other question was probably wrong. I based it on the last paragraph of section 7.5 of the clang Objective-C Automatic Reference Counting documentation:

With the exception of retains done as part of initializing a __strong parameter variable or reading a __weak variable, whenever these semantics call for retaining a value of block-pointer type, it has the effect of a Block_copy. The optimizer may remove such copies when it sees that the result is used only as an argument to a call.

I took “these semantics” to mean the whole document, but if “these semantics” to refers to only section 7.5, then ARC only inserts a Block_copy for a block that is captured by a block.

like image 35
rob mayoff Avatar answered Sep 21 '22 17:09

rob mayoff