解释两次发生的alloc/init

Bil*_*ess 2 iphone memory-management objective-c ios

我意识到这个问题可能听起来很愚蠢,但只是忍受我.我构建了一个应用程序来帮助新开发人员围绕iPhone保留内存(还没有ARC).它简单明了,有4个按钮,初始化,访问,保留和释放.非常自我解释.我正在显示我的字符串对象的保留计数,它是我们戳戳和刺激的目标.(请不要讲授[myVar retainCount]的使用,我已经知道了)

这些东西永远不会成为真正的应用程序,只是玩弄它的乐趣,并希望帮助人们了解内存的工作原理.我保留和释放所有工作都很棒.我的问题是,如果我调用myString = [[NSMutableString alloc] init],为什么我的保留计数会回落到1; 再次.我可以将保留计数提高到40,但在调用alloc/init后我会回到零.我没有在任何地方泄漏,只是好奇myString会发生什么,如果/再次调用alloc/init.

bbu*_*bum 28

我的问题是,如果我myString = [[NSMutableString alloc] init];再次打电话,为什么我的保留计数会回落到1 ?

因为你无法理解Objective-C的一个非常基本的概念; myString不是an的实例NSMutableString,而是对实例的引用.如果你是:

myString = [[NSMutableString alloc] init];
myString = [[NSMutableString alloc] init];
Run Code Online (Sandbox Code Playgroud)

您现在有两个NSMutableString实例,一个泄露.

如果你:

myString = [[NSMutableString alloc] init];
otherString = myString;
Run Code Online (Sandbox Code Playgroud)

您现在拥有一个带有两个引用的NSMutableString实例.

在所有三个分配中,NSMutableString实例将具有+1保留计数,因此,您必须平衡每个分配release或您将泄漏.

将保留计数视为绝对计数是疯狂的途径.或者,充其量,绝对保留计数的有用范围是如此有限,以至于了解它不适用于真实世界的iOS编程.


这有点重复:

retainCount对象的是棘手的事.

如果您继续沿着这条路走下去,您应该了解以下细节:

  • retainCount 永远不会回归0
  • 消息传递悬空指针不能保证崩溃
  • 一旦您通过任何系统API传递了对象,由于实现细节,就无法知道retain count
  • 由于实现细节,任何系统类的任何子类都可能具有未知的保留计数
  • 保留计数从不反映对象是否自动释放
  • autoreleases实际上是特定于线程的,而保留计数是线程全局的
  • 有些类在某些时候用单例实现(NSString,NSNumber的某些值)
  • 实施细节从平台变为平台,从发布到发布
  • 尝试swizzle retain/ release/ autorelease将无法工作,因为某些类实际上没有使用这些方法来维护保留计数(实现细节,每个平台/发布的更改等).

如果您要教授保留/释放,您应该将保留计数视为三角形并完全关注"如果您增加RC,则必须减少它".


fil*_*ipe 11

当你打电话时myString = [[NSMutableString alloc] init];,你不是"再次调用alloc/init".您没有在同一个实例上调用方法.您正在分配和初始化一个新实例,这是一个与之前完全不同的对象.

如果你正在使用一个包含你保留的对象的变量,那么是的,你正在泄漏它.

  • 如果您使用Leak配置文件在Instruments中运行应用程序,则可以看到泄漏.这是经典的C指针混淆 - 您的变量是指向已分配内存的指针.如果您分配新内存并更新指向新内存的指针而没有先向系统标记您已完成上一次分配,则会泄露(如filipe所说). (2认同)