13

更新:这已在 iOS 6.1 DP3 SDK 中修复。

在使用默认发布构建配置(调试似乎工作正常)使用 ARC 构建时,我发现了一个释放后使用的崩溃。当在具有非常量条件的 if 范围内创建对象,将其分配给范围外的变量,然后仅使用 Objective-C 数组或字典文字引用该变量时,就会出现问题。

这是我设法找到的最小的可重现案例:

void test(BOOL arg)
{
    id obj = nil;

    if (arg) {
        obj = [NSObject new];
    }

    // obj already deallocated here
    @[obj];

    // but using NSArray works
    //[NSArray arrayWithObject:obj];

    // @[obj] works if obj is referenced i.e. by NSLog print out
    //NSLog(@"%@", obj);
}

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        test(YES);
    }
    return 0;
}

当我在启用僵尸对象的情况下构建和运行它时,我收到以下错误消息:

-[NSObject retain]: message sent to deallocated instance 0x100109100

正如我在代码中评论的那样,如果obj以其他方式引用它,它可以正常工作,比如 withNSLog或 using NSArray。我是否误解了如何使用 ARC 和作用域释放对象,或者这是 LLVM 或 Clang 中的优化错误?

我正在使用 Xcode 4.5.2 和 clang 版本 4.1 (tags/Apple/clang-421.11.66) (基于 LLVM 3.1svn)。我可以在为 iOS 模拟器和 Mac OS X 构建 x86 64 位时重现它,并且我很确定在为 ARM 构建时会出现同样的问题,因为在 iPhone 上运行发布构建时首次发现了该问题。

我已经向 Apple 提交了错误报告并创建了一个开放的雷达报告

如果有的话,我错过了什么?

更新,做了一些更多的实验:

正如 Gabro 指出的那样,编译器会转换@[][NSArray arrayWithObjects:count:]语句,所以我做了一些测试:

// works
id a[] = {obj};
[NSArray arrayWithObjects:a count:1];

// does not work
const id *b = (id[]){obj};
[NSArray arrayWithObjects:b count:1];

// does not work
[NSArray arrayWithObjects:(id[]){obj} count:1];

所以我的猜测是,当结合 ARC 和匿名 C 数组时会发生这种情况。

4

2 回答 2

1

我刚刚测试了为 OSX (x86 64) 和 iOS Simulator 构建的以下代码,但我无法重现该错误

 void test(BOOL arg) {
     id obj = nil;

    if (arg) {
        obj = [NSObject new];
    }
    @[obj];
    NSLog(@"Hi there");
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        test(YES);
    }
    return 0;
}

上面的代码只是Hi there在控制台中打印并返回。

我的配置和你的一样:XCode 4.5.2 和 Apple clang 4.1 (tags/Apple/clang-421.11.66) (基于 LLVM 3.1svn) 作为编译器。

编辑

我还尝试从命令行编译(在#include <Foundation/Foundation.h> 上面示例的开头添加之后)使用

clang -fobjc-arc -framework Foundation main.m

结果又是

2012-12-03 12:47:45.647 a.out[39421:707] Hi there

编辑 2 正如评论中指出的那样,可以重现增加优化级别的错误-O0。总结:

clang -O0 -fobjc-arc -framework Foundation main.m

该程序按预期工作

clang -O1 -fobjc-arc -framework Foundation main.m

问题中出现的错误出现了。这适用于任何优化级别-O0

这绝对是编译器中的一个错误。

于 2012-12-03T18:37:19.020 回答
1

You're not missing anything. It's a compiler bug.

于 2012-12-03T19:51:44.670 回答