更新:这已在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数组时会发生这种情况。
答案 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)
你没有遗漏任何东西。这是一个编译器错误。