即使在范围之外使用,在范围内创建的对象也会被释放

时间:2012-12-03 16:26:50

标签: objective-c automatic-ref-counting llvm clang

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

我在使用默认版本构建配置使用ARC构建时跟踪了释放后使用后的崩溃(调试似乎工作正常)。在具有非常量条件的if-scope中创建对象,将其分配给范围外部的变量,然后仅使用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;
}

当我使用zombie对象构建并运行它时,我收到以下错误消息:

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

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

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

我已经向Apple提交了错误报告并创建了open radar report

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

更新,做了更多实验:

正如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数组时会发生这种情况。

2 个答案:

答案 0 :(得分:1)

我刚刚测试了以下代码,这些代码都是为OSX(x86 64)和iOS模拟器构建的,我无法重现该错误

 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版(标签/ 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

以上的任何优化级别都是如此

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

答案 1 :(得分:1)

你没有遗漏任何东西。这是一个编译器错误。