目标C-自归零弱指针意外行为



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

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 );

此代码的输出为:

resultText =   value1 = Hello: 1  value2 = Hello 2  value1 = (null)  value2 = Hello 2

我本以为:

resultText =   value1 = Hello: 1  value2 = Hello 2  value1 = (null)  value2 = (null)

第二CCD_ 1也可以是CCD_。请注意value1value2的内容之间的差异。value2缺少冒号。我不明白为什么当value2设置为nilweakValue2不自零。一旦我把冒号放回字符串中,我就会得到我期望的结果。在小牛队运行此代码时,我没有看到这种行为。

有人知道为什么会发生这种事吗?

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

问题是您对弱引用的使用与系统的实现细节相冲突。

当且仅当弱引用所引用的对象被解除分配时,该引用才会无效。其中的时间实际上并不能保证,只要引用不是NULL,引用的对象仍然是可行的。

对singleton的弱引用(从未被释放的真正singleton)永远不会无效。

NSString、NSNumber、NSDate和其他一些类有时被实现为某些值的singleton。或者很多时候,取决于平台。

因此,对其中一个类的实例的弱引用可能无效,也可能不无效,因为该实例实际上可能是单例。

请注意,标记的指针实际上是定义的singleton。

要修复吗?

不要创建对系统基元/值类的弱引用

NSString它不是具体的类,它是许多其他类的接口和工厂。

我发现value1是__NSCFString类的实例,但value2是NSTaggedPointerString类的实例。类NSTaggedPointerString不支持retain和release(我尝试向它注入一些块方法)。

如果你打印这个例子的retainCount,你会得到这样的结果:

po [value2 retainCount] //18446744073709551615

如果你从格式中删除符号":",你会得到这样的结果:

 resultText =   value1 = Hello 1  value2 = Hello 2  value1 = Hello 1  value2 = Hello 2

之所以发生这种情况,是因为上面的字符串是NSTaggedPointerString类的实例。我认为这是非常奇怪的行为。

p.S.

如果您在value2字符串中添加":",您将得到结果:

resultText =   value1 = Hello: 1  value2 = Hello: 2  value1 = (null)  value2 = (null)

:)

UPD

若字符串的长度小于8,那个么它的字符串将被缓存到内存中。

UPD-2

我已将代码更改为:

value1 = [NSString stringWithFormat: @"Heo: %d", 1];
    value2 = [NSString stringWithFormat: @"Heo: %d", 1];
    if (value2 == value1)
    {
        NSLog(@"same strings");
    }

我得到的结果是:"相同的字符串"

相关内容

  • 没有找到相关文章

最新更新