【发布时间】:2012-01-30 03:44:10
【问题描述】:
我正在将一段代码迁移到自动引用计数 (ARC),并让 ARC 迁移器抛出错误
NSInvocation 的 setArgument 与一个对象一起使用是不安全的 __unsafe_unretained 以外的所有权
在我使用类似的东西分配对象的代码上
NSDecimalNumber *testNumber1 = [[NSDecimalNumber alloc] initWithString:@"1.0"];
然后使用
将其设置为 NSInvocation 参数[theInvocation setArgument:&testNumber1 atIndex:2];
为什么它阻止你这样做?使用__unsafe_unretained 对象作为参数似乎同样糟糕。例如下面的代码在ARC下会导致崩溃:
NSDecimalNumber *testNumber1 = [[NSDecimalNumber alloc] initWithString:@"1.0"];
NSMutableArray *testArray = [[NSMutableArray alloc] init];
__unsafe_unretained NSDecimalNumber *tempNumber = testNumber1;
NSLog(@"Array count before invocation: %ld", [testArray count]);
// [testArray addObject:testNumber1];
SEL theSelector = @selector(addObject:);
NSMethodSignature *sig = [testArray methodSignatureForSelector:theSelector];
NSInvocation *theInvocation = [NSInvocation invocationWithMethodSignature:sig];
[theInvocation setTarget:testArray];
[theInvocation setSelector:theSelector];
[theInvocation setArgument:&tempNumber atIndex:2];
// [theInvocation retainArguments];
// Let's say we don't use this invocation until after the original pointer is gone
testNumber1 = nil;
[theInvocation invoke];
theInvocation = nil;
NSLog(@"Array count after invocation: %ld", [testArray count]);
testArray = nil;
由于testNumber1的过度释放,因为临时的__unsafe_unretainedtempNumber变量在原来的指针设置为nil后没有持有它(模拟一个在原来的之后使用调用的情况对参数的引用已经消失)。如果 -retainArguments 行未注释(导致 NSInvocation 保留参数),则此代码不会崩溃。
如果我将testNumber1 直接用作-setArgument: 的参数,则会发生完全相同的崩溃,如果您使用-retainArguments,它也会得到修复。那么,为什么 ARC 迁移器会说使用强保持指针作为 NSInvocation 的 -setArgument: 的参数是不安全的,除非您使用 __unsafe_unretained 的东西?
【问题讨论】:
标签: objective-c cocoa automatic-ref-counting