Objective C - Self Zeroing弱指针意外行为

hva*_*rug 3 weak-references objective-c automatic-ref-counting

我最近从小牛升级到优胜美地,现在我的单元测试失败了.问题归结为字符串内容的弱指针中的拼写错误.请参阅以下示例代码:

NSString* value1;
NSString* value2;
__weak NSString* weakValue1;
__weak NSString* weakValue2;
NSMutableString* resultText = [NSMutableString new];

@autoreleasepool
{
    value1 = [NSString stringWithFormat: @"Hello: %d", 1];
    value2 = [NSString stringWithFormat: @"Hello %d", 2];
    weakValue1 = value1;
    weakValue2 = value2;

    [resultText appendFormat: @"  value1 = %@", weakValue1];
    [resultText appendFormat: @"  value2 = %@", weakValue2];

    value1 = nil;
    value2 = nil;
}
[resultText appendFormat: @"  value1 = %@", weakValue1];
[resultText appendFormat: @"  value2 = %@", weakValue2];

NSLog( @"resultText = %@", resultText );
Run Code Online (Sandbox Code Playgroud)

此代码的输出是:

resultText =   value1 = Hello: 1  value2 = Hello 2  value1 = (null)  value2 = Hello 2
Run Code Online (Sandbox Code Playgroud)

我原以为:

resultText =   value1 = Hello: 1  value2 = Hello 2  value1 = (null)  value2 = (null)
Run Code Online (Sandbox Code Playgroud)

第二个value2也是,(null)但事实并非如此.请注意value1和的内容之间的区别value2.value2缺少冒号.我不明白为什么设置为weakValue2自零.一旦我将结肠放回到字符串中,我就得到了我期望的结果.在Mavericks中运行此代码时,我没有看到这种行为.value2nil

有谁知道为什么会这样?

我在这个问题中注意到多线程的有效点可能导致弱指针在时间上不是自零,但这不是这里发生的事情.首先,我不是多线程的,如果我单步执行代码并查看变量而不是使用NSLog打印它,我会得到完全相同的结果.

bbu*_*bum 5

问题是您使用弱引用会与系统的实现细节发生冲突.

如果 - 并且 - 如果它引用的对象被释放,则弱引用将被取消.其中的时间实际上并未得到保证,只要引用为非NULL,所引用的对象仍然可行.

对单例(永不释放的真正单例)的弱引用永远不会被无效.

NSString,NSNumber,NSDate和一些其他类在某些时候被实现为某些值的单例.或者很多时候,取决于平台.

因此,对这些类之一的实例的弱引用可能会也可能不会被取消,因为实例实际上可能是单例.

请注意,根据定义,标记指针实际上是单例.

修理?

不要创建对系统原语/值类的弱引用.

  • @AndrewRomanov实现细节实际上是不透明的,可能因平台,版本而异.运行时源可用.长和短; 如果在对象的引用上设置了低位,则该对象被视为标记指针,对象的"地址"实际上是对象本身(即没有分配).所以,它不是真正的单例,但没有分配,没有解除分配,弱引用永远不会因为这个而无效.https://www.mikeash.com/pyblog/friday-qa-2012-07 -27-让 - 构建 - 标记 - pointers.html (2认同)