保留计数显示最大整数

6

当我尝试打印对象的retainCount时,我得到了2147483647。为什么会出现这样的结果?它不应该是1吗?

NSString *myStr = [NSString new];
NSUInteger retCount = [myStr retainCount];
NSLog(@"refCount = %u", retCount);

2011-09-08 17:59:18.759 Test[51972:207] refCount = 2147483647

我使用的是XCode 4.1版本,尝试了GCC 4.2和LLVM GCC 4.2编译器,结果相同。垃圾回收选项不受支持。


如果您打印以下内容:NSLog(@"refCount = %d", retCount);会发生什么? - James Webster
NSLog(@"refCount = %d", retCount); 打印出相同的结果... - JastinBall
可能是何时使用-retainCount?的重复问题。 - jscs
@AppleVijay, DarkDust - 我刚刚阅读了常见问题解答,现在一切都没问题了!谢谢你们的建议。 - JastinBall
永远不要调用retainCount,它是无用的。 - Sven
4个回答

15

NSString 在内存管理方面有些特殊。字符串字面量(例如 @"foo")是单例,每个具有相同内容的字符串都是同一个对象,因为它无法被修改。由于 [NSString new] 始终创建一个空字符串,该字符串不能被修改,因此您将始终获得无法释放的同一实例(因此保留计数高)。

尝试这个片段:

NSString *string1 = [NSString new];
NSString *string2 = [NSString new];
NSLog(@"Memory address of string1: %p", string1);
NSLog(@"Memory address of string2: %p", string2);

你会发现这两个字符串具有相同的内存地址,因此它们是同一个对象。


4
附加说明:这可能是基于flyweight设计模式的原因,而这句话:“对于永远不会被释放的对象(也就是,它们的释放方法什么也不做),此方法应返回UINT_MAX”(摘自NSObject-Class-Reference) - thomas

12

这并没有直接回答你的问题,但是retainCount并不是很有用并且不应该用于测试。请参考这篇SO文章了解详情。 何时使用-retainCount?


3
+1,除了出于好奇心以外,绝对没有必要查看retainCount。如果你评估retainCount,那么你正在做一些非常错误的事情。 - DarkDust
5
检查对象的保留计数的唯一效果是,你最终会回到这里发布困惑的问题,问为什么那个数字会在没有你的情况下移动。答案是:那个数字会在没有你的情况下移动。因此不要使用它来调试你的保留/释放代码。 - Dan Ray

4

虽然NSString有点奇怪(框架中还有其他类似情况),但你可能也会在其他类中遇到这个问题 - 这是创建单例对象的一种方法之一。

单例只在应用程序中存在一次,重要的是它永远不会被释放!因此,它将覆盖NSObject的某些方法,包括(但不限于):

- (id)release {
    // Ignore the release!
    return self;
}

- (NSUInteger)retainCount {
    // We are never going to be released
    return UINT_MAX;
}

这个对象永远不能被释放,并通过保持极高的引用计数告诉框架它是一个单例。

点击此链接了解更多关于单例对象的信息。


2
它告诉框架没有这样的东西;retainCount的返回值在框架中从未被使用(除了一些特殊情况,这些情况仅限于非常特定的使用范围)。在单例模式的上下文中存在覆盖retainCount的建议本身就是浪费时间。 - bbum
抱歉,我的表达方式可能有些过于明确了——这只是一个措辞非常糟糕的句子!我想表达的是类似于http://www.cocoadev.com/index.pl?SingletonDesignPattern中的内容——即“表示无法释放的对象” :) - deanWombourne

1
我在NSString方面看到过这种情况几次,当您尝试以这种方式查看字符串的retainCounts时,retainCount返回的是最大计数而不是实际计数。
请尝试以下操作;
NSString *myStr = [[NSString alloc] init];
NSUInteger retCount = [myStr retainCount];
NSLog(@"refCount = %u", retCount);

编辑:恢复了NSUInteger


1
retainCount 返回 NSUInteger。虽然这个方法没什么用,但你至少应该使用正确的返回类型。无符号整数和有符号整数并不是透明可互换的。 - bbum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接