NSString长度和retainCount。需要澄清

时间:2011-07-18 00:25:17

标签: objective-c memory-management

根据以下代码,请提供建议

NSString *str= [[NSString alloc] initWithString:@"Hello world"];   

NSLog(@"Length: %lu\n", [str length]);              // 11
NSLog(@"Retain count is %lu\n", [str retainCount]); //1152921504606846975

[str release];

NSLog(@"%lu\n", [str length]);                      // 11
NSLog(@"Retain count is %lu\n", [str retainCount]); //1152921504606846975
  1. 最初我想知道为什么数字这么大但后来看到了post explaining it。让我问这个问题......为什么我使用%d vs %lu时这个数字会发生很大变化。最初,我使用%d,但收到警告说“转换指定类型为int但参数的类型为NSUInteger(也称为unsigned long)。修复是将%d更改为{{ 1}}“

  2. 为什么保留计数不减少? %lu发送str

  3. 后,大数字仍然显示不变
  4. 为什么我发送release后仍然可以访问str

2 个答案:

答案 0 :(得分:8)

这可能是一个难以接受的答案,但这是你应该做的:

  1. 不要担心。(就%d /%lu而言,这些说明符只是期望不同的数据类型,而%d(int)的范围要小得多,且不同于% lu(unsigned long))
  2. 不要担心。
  3. 不要这样做,尤其不要依赖它。
  4. 可能是因为你以一个常量字符串(@"Hello world")开始,当你调用release时内存没有被释放,并且retainCount很大。但是如果你不得不关心retainCount,你做错了。

    你正在正确的位置释放字符串,这才是最重要的 - 不要试图在以后使用它。

答案 1 :(得分:0)

最终,行为是由NSString的实现定义的 - 只要在每种情况下正确使用retain / release,你就会安全。

可能发生的事情:NSString文字是不朽的。你可以写while (1) { [@"String" release]; }而且没有问题。

您调用的副本可能会返回指向字符串文字的指针。在伪代码中:

- (id)initWithString:(NSString *)str
{
    self = [super init];
    if (self != nil) {
        if ([str _isStringLiteral] || [str _isImmutable]) {
            [self release];
            return [str retain];
        }
        ...
}

在这种情况下,当您通过[[NSString alloc] initWithString:stringLiteral]时,会返回指向字符串文字的指针。因为将release发送到不朽的字符串文字什么都不做,你可以看到为什么它仍然是一个有效的对象,你可以认为它是一个已发布的对象。

永远不要依赖这些细节/优化,只需使用正常的生命周期并重新计算,你就可以了。