如何在ARC模式下验证引用计数?

tom*_*oft 34 iphone ios automatic-ref-counting

我曾经在调试器下使用[myVar retainCount]验证我的一些变量是否具有预期的保留计数,尤其是对于没有自定义dealloc的var.

你如何在ARC模式下这样做?你如何确保没有内存泄漏?

注意:我理解ARC应该为我处理这个问题,但生活远非完美,而在现实生活中,你有一些有时被第三方库分配的对象(使用retain?)并且永远不会被解除分配.

我这样做的图像:

MyObj *myObj=[[MyObj alloc] init];
Run Code Online (Sandbox Code Playgroud)

然后我打电话

[somethingElse doSomethingWithMyObj:myObj];
Run Code Online (Sandbox Code Playgroud)

后来,我做到了

myObj=NULL;
Run Code Online (Sandbox Code Playgroud)

如果我的程序工作正常,我的期望是myObj正在被销毁,但似乎并非如此......

那么我该如何跟踪这一点,特别是如果我没有管理的东西?

现在,关于工具:在我的mac(使用5 Meg)上运行内存工具似乎非常困难,无需重新启动mac并从头开始.这真烦人!即使在程序启动之前,仪器仍然会崩溃,那么是否有更改解决方案?

rob*_*off 99

CFGetRetainCount即使在ARC下,您也可以使用Objective-C对象:

NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)myObject));
Run Code Online (Sandbox Code Playgroud)

但是,这对于调试来说并不是特别有用,原因在于别处有详细描述.如果您需要了解保留和释放对象的位置,请使用Allocations工具查看此答案以获取帮助.

我发现检查保留计数的唯一情况实际上是有用的dealloc,当一些东西保留并自动释放被解除分配的对象时.这会在自动释放池耗尽后导致崩溃.您可以通过检查每条消息之前和之后的保留计数来查明原因.通过这种方式,我发现observationInfo方法(它本身通常只对调试有用)保留和自动释放self.然而,即使是这种问题通常也可以在不检查保留计数的情况下解决,只需将整个体包裹dealloc在一个@autoreleasepool块中即可.

但是,保留计数可用于了解某些类的实现.(这只是为了娱乐或好奇!不要依赖生产代码中的未记录的实现细节!)

例如,在@autoreleasepoolin中立即尝试main:

NSNumber *n0 = [[NSNumber alloc] initWithInt:0];
NSLog(@"0 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef)n0));
// Prints 2 in my test
Run Code Online (Sandbox Code Playgroud)

所以NSNumber有可能高速缓存(或至少是重新使用)的一些实例.但不是其他人:

n0 = [[NSNumber alloc] initWithInt:200];
NSLog(@"n0 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef) n0));
// Prints 1 - I am the sole owner of this instance.  There could be weak
// or unretained references to it, but no other strong references.

NSNumber *n1 = [[NSNumber alloc] initWithInt:200];
NSLog(@"n1 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef) n1));
// Prints 1 again.  New instance with same value as prior instance.
// You could of course compare pointers to see that they are separate
// instances.
Run Code Online (Sandbox Code Playgroud)

你甚至可以发现NSNumber如果你alloc没有初始化那么返回一个单例:

n1 = [NSNumber alloc];
NSLog(@"n1 reference count = %ld", CFGetRetainCount((__bridge CFTypeRef) n1));
// Prints -1.
Run Code Online (Sandbox Code Playgroud)

(请注意,您还可以NSNumber通过查看可在http://opensource.apple.com上找到的Core Foundation源代码了解许多详细信息.但是,如果您查看对象的保留计数,谁知道您可能会发现什么与Core Foundation中的对象没有免费桥接?)

  • 不,不是.它在ARC下比其他方式更具误导性(因为编译器会在优化级别,发布和潜在的调试之间移动保留/释放/自动释放调用). (37认同)
  • 哇.这是一个编辑的地狱!+1!有趣的细节; 值为"200"的`NSNumber`示例将改变不同平台和不同操作系统版本上的行为,因为实现细节(例如标记指针),进一步暗示了`retainCount`的不可预测性. (9认同)
  • 这很适合调试. (3认同)

Col*_*ler 41

你没有.ARC为您处理内存管理,并且不允许您调用retainCount,即使您可以看到它,它返回的数字对您来说也毫无意义.如果您愿意,您应该使用Leaks and Allocations工具在Instruments中进行内存分析.这是查看和查看应用程序如何分配内存以及捕获内存中任何不当使用内存的最佳方式.

  • 然后你需要看看为什么仪器会崩溃,如果你的跟踪方式太多,请忘记,或者你需要重新安装开发工具.如果仪器一直在崩溃,那么我可能会提出另一个问题,或者(可能更好)带到Apple开发者论坛. (5认同)

UIA*_*dam 31

不管是否使用ARC,都不应该将retainCount用于任何事情.

何时使用-retainCount?


Hen*_*rtz 15

如果在"对象列表"中输入类名称或指针地址,请使用"仪器"并找到要跟踪的对象.

找到它后,点击实例上的显示箭头.这将带您进入保留和关系的历史视图.

如果展开右侧详细视图,您还将看到每个保留/释放的callstack.

仪器显示对象历史和callstack细节