objective-c-blocks和ARC – 发布版本的复制或崩溃(由优化级引起)

我正在使用 Xcode 4.3.3并开发iOS 5.0.在开发ARC iOS应用程序时,我已经开始使用块作为异步操作的回调机制.该应用程序在模拟器和设备上正常工作.

然后我第一次运行该分析器,并且它几乎马上就开始崩溃 – 特别是在尝试调用一个回调块时,EXC_BAD_ACCESS.

经过一番调查,很明显,行为的差异是因为在认情况下,分析器运行在“发布模式” – 特别是优化级别设置为“最快,最小[-Os]”而不是“无[-O0] ”.

例如,以下代码(针对此问题简化)将在尝试执行callbackBlock时崩溃:

- (void) setCallbackBlock:(void (^)(Nsstring *input))block
{
    callbackBlock = block;
}

- (void) invokeCallbackWithInput:(Nsstring *)input
{
    if (callbackBlock) {
        callbackBlock(input);
    }
}

调试到它,调用setCallbackBlock,优化级别设置为“None”,传入的块将是一个NsstackBlock,并且callbackBlock将成为一个NSMallocBlock.

然而,优化级别“最快,最小”,仍然是NsstackBlock.

更改setter代码以使用[block copy]来修复崩溃问题(基于iOS 5 blocks crash only with Release Build).

然而,另一个相关的问题表明,ARC-Why does Objective-C block still work without copying it to the heap?中的ARC – 块变量被复制到堆中不是必需的

所以我的问题:这里发生了什么,为什么? (另外,这两个答案如何正确??)

编辑:
要澄清如何声明callbackBlock – 就在我的@implementation之上,那些方法是这样的:

@interface MyClass ()
{
    void (^callbackBlock)(Nsstring *input);
}

@end

解决方法

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

我实际上认为the other question的答案是错误的,因为它没有回答关于ARC中的块的特定问题.问题是将一个基于堆栈的块从一个函数/方法传递给另一个.答案是一些不同的东西,这是捕获一个块内的__block变量.这是一个不同的问题.

您的问题的答案是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.

所以这样做的方式是,当你传递一个块(在你的情况下是在堆栈上分配的块文字)时,编译器在初始化该调用的参数时不会复制该块.被调用函数方法有责任在需要时复制该块本身.

当ARC从函数方法返回块时,ARC自动复制块.在这种情况下,编译器知道它必须为你做一个复制到堆,所以它.

所以你的设置者应该做一个块拷贝,甚至用ARC.

我希望有帮助.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...