blocks and ARC - copy or crash with release build (caused by optimization level)

后端 未结 2 709
别那么骄傲
别那么骄傲 2021-02-14 16:02

I\'m using Xcode 4.3.3 and developing for iOS 5.0+. In development of an ARC iOS application, I\'ve started using blocks as a callback mechanism for asynchronous operations. T

相关标签:
2条回答
  • 2021-02-14 16:36

    This is a long comment on Firoze's answer.

    The document Automatic Reference Counting" section 7.5 states:

    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.

    And this is the behavior I have seen.

    So if callbackBlock is a strong instance variable then ARC should copy any stack-allocated block pass in block. I.e. the Debug version was correct and the Release version is a compiler bug.

    If this is correct then you've found a compiler bug and should report it. Reporting it would not be bad either way, it should produce a definitive answer.

    0 讨论(0)
  • 2021-02-14 17:01

    So my question: What's going on here, and why? (Also, how can both of those answers be correct...?)

    I actually think the answer to the other question is wrong, in that it doesn't answer that particular question about blocks in ARC. The question is about passing a stack based block from one function/method to another. The answer is about something different, which is capturing __block variables within a block. That's a different issue.

    The answer to your question is in the FAQ of the Transitioning to ARC Release Notes:

    Blocks “just work” when you pass blocks up the stack in ARC mode, such as in a return. You don’t have to call Block Copy any more. You still need to use [^{} copy] when passing “down” the stack into arrayWithObjects: and other methods that do a retain.

    So the way this works is that when you pass a block (in your case a block literal allocated on the stack), the compiler does not copy that block when it initializes the parameter for that call. The called function or method has the responsibility to copy that block itself if needed.

    Where ARC does copy blocks automatically is when you are returning a block from a function or method. In that case, the compiler knows that it must do a copy to the heap for you, and so it does.

    So your setter should be doing a block copy, even with ARC.

    I hope that helps.

    0 讨论(0)
提交回复
热议问题