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

2

20

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].

Calista answered 4/5, 2012 at 17:11 Comment(0)
O
10

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.

Outbreed answered 14/5, 2012 at 1:14 Comment(3)
Do you know that I am asking in reference to an Automatic Reference Counted environment? It seems your foo/bar example wouldn't be a problem in ARC ...?Calista
Yeah, sorry. Your answer, or the supplied apple documentation says nothing about whether ARC automatically moves a block to the heap when assigned to an instance variable. It seems the answer to this question will have to come from the clang Objective-C Automatic Reference Counting documentation.Calista
Thanks for all the effort sbooth. Wow, this doc is so hard to understand. Actually, I would read it that the compiler -will- insert a Block_copy. It seems like an ivar defaults to __strong and thus the assignment would "call for retaining a value of block pointer type" and thus insert the Block_copy. Thought it would be great to have a definitive answer, I think for now I'll settle for storing blocks in a @property(copy).Calista
C
4

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.

Catullus answered 4/5, 2012 at 17:23 Comment(2)
I agree it isn't clear what "these semantics" is referring toOutbreed
I spoke to the Apple engineer that wrote this section. He said "these semantics" refers to the whole document. Thus a Block_copy should be automatically inserted. It seems that maybe this was a bug early on with blocks that was later fixed.Calista

© 2022 - 2024 — McMap. All rights reserved.