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

时间:2023-01-23 14:59:56

I used to verify that some of my variables had the expected retain count using [myVar retainCount] under the debugger, especially for var that did not have a custom dealloc.

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

How do you do this in ARC mode? How do you ensure that there are no memory leaks?

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

Note: I understand that ARC should handle this for me, but life is far from being perfect, and in real life you have objects that are sometimes allocated by third party libraries (using retain?) and never deallocated.

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

Image that I do this:

我这样做的图像:

MyObj *myObj=[[MyObj alloc] init];

then I call

然后我打电话

[somethingElse doSomethingWithMyObj:myObj];

and later, I do

后来,我做到了

myObj=NULL;

If my program is working fine, my expectation is that myObj is being destroyed, but it appears not to be the case...

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

So how can I track this, especially if somethingElse is not managed by me?

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

Now, about the tools: it seems extremely hard to run memory tools on my mac (with 5 Meg) without rebooting the mac and starting from scratch. This is really annoying! Instruments keep crashing even before the program has started, so is there an alterante solution?

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

7 个解决方案

#1


93  

You can use CFGetRetainCount with Objective-C objects, even under ARC:

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

NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)myObject));

This is not particularly useful for debugging, though, for reasons amply described elsewhere. If you need to understand where an object is being retained and released, check out this answer for help using the Allocations instrument.

然而,这对于调试来说并不特别有用,原因在于其他地方已充分描述的原因。如果您需要了解保留和释放对象的位置,请使用Allocations工具查看此答案以获取帮助。

The only case I've found where examining the retain count is actually useful is in a dealloc method, when something retains and autoreleases the object being deallocated. This will cause a crash later when the autorelease pool is drained. You can pinpoint the cause of this by checking the retain count before and after each message. In this way I discovered that the observationInfo method (which is itself usually only useful for debugging) retains and autoreleases self. However, even this sort of problem can usually be solved without examining the retain count, simply by wrapping the entire body of dealloc in an @autoreleasepool block.

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

However, the retain count can be used to learn about the implementation of some classes. (Only do this for entertainment or curiosity! Never rely on undocumented implementation details in production code!)

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

For example, try this immediately inside the @autoreleasepool in main:

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

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

So NSNumber likely caches (or at least reuses) some instances. But not others:

因此,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.

You can even discover that NSNumber returns a singleton if you alloc but don't initialize:

您甚至可以发现NSNumber在您分配但不初始化时返回单例:

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

(Note that you can also learn many details about NSNumber by looking at the Core Foundation source code, which is available at http://opensource.apple.com. But who knows what you might find if you look at the retain count of objects that aren't toll-free-bridged with objects in Core Foundation?)

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

#2


41  

You don't. ARC handles the memory management for you and does not allow you to call retainCount and even if you could see it, the number it returns is meaningless for you. If you want to you should be doing memory profiling in Instruments with the Leaks and Allocations instruments. That is the best way to look and see how your application is allocating memory and catch any improper use of memory there.

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

#3


32  

You should never use retainCount for anything, with or without ARC.

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

When to use -retainCount?

什么时候使用-retainCount?

#4


15  

Use Instruments and locate the object you want to track by searching for the class name or pointer address if you have it while in in "Objects List".

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

When you have located it, hit the disclosure arrow on the instance. This brings you to a history view for retains and relases.

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

If you expand the right side detail view you will also see the callstack for each retain/release.

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

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

#5


3  

I believe the only way is to profile your application using the Allocations instrument. You will need to click on the info descriptor (the 'i' next to Allocation in the left pane) and click on "Record Reference Counts". You can then profile your app and do a search for the specific class you're looking to inspect. From there you can find the retain count in the Extended Detail pane for each instance of the class.

我认为唯一的方法是使用Allocations工具分析您的应用程序。您需要单击信息描述符(左侧窗格中“分配”旁边的“i”),然后单击“记录参考计数”。然后,您可以对您的应用进行概要分析,并搜索您要检查的特定类。从那里,您可以在“扩展详细信息”窗格中找到该类的每个实例的保留计数。

You can also do this using Leaks as well (since I believe it's a variation of the Allocations instrument).

您也可以使用Leaks执行此操作(因为我认为它是Allocations工具的变体)。

#6


1  

Get the object's retainCount?

获取对象的retainCount?

You can just make a breakpoint and input the command below to get the object's retainCount

您可以创建一个断点并输入以下命令来获取对象的retainCount

po object.retainCount

#7


0  

You don't. Apple say you don't need to as ARC will handle it for you.

你没有。 Apple说你不需要,因为ARC会为你处理它。

#1


93  

You can use CFGetRetainCount with Objective-C objects, even under ARC:

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

NSLog(@"Retain count is %ld", CFGetRetainCount((__bridge CFTypeRef)myObject));

This is not particularly useful for debugging, though, for reasons amply described elsewhere. If you need to understand where an object is being retained and released, check out this answer for help using the Allocations instrument.

然而,这对于调试来说并不特别有用,原因在于其他地方已充分描述的原因。如果您需要了解保留和释放对象的位置,请使用Allocations工具查看此答案以获取帮助。

The only case I've found where examining the retain count is actually useful is in a dealloc method, when something retains and autoreleases the object being deallocated. This will cause a crash later when the autorelease pool is drained. You can pinpoint the cause of this by checking the retain count before and after each message. In this way I discovered that the observationInfo method (which is itself usually only useful for debugging) retains and autoreleases self. However, even this sort of problem can usually be solved without examining the retain count, simply by wrapping the entire body of dealloc in an @autoreleasepool block.

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

However, the retain count can be used to learn about the implementation of some classes. (Only do this for entertainment or curiosity! Never rely on undocumented implementation details in production code!)

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

For example, try this immediately inside the @autoreleasepool in main:

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

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

So NSNumber likely caches (or at least reuses) some instances. But not others:

因此,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.

You can even discover that NSNumber returns a singleton if you alloc but don't initialize:

您甚至可以发现NSNumber在您分配但不初始化时返回单例:

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

(Note that you can also learn many details about NSNumber by looking at the Core Foundation source code, which is available at http://opensource.apple.com. But who knows what you might find if you look at the retain count of objects that aren't toll-free-bridged with objects in Core Foundation?)

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

#2


41  

You don't. ARC handles the memory management for you and does not allow you to call retainCount and even if you could see it, the number it returns is meaningless for you. If you want to you should be doing memory profiling in Instruments with the Leaks and Allocations instruments. That is the best way to look and see how your application is allocating memory and catch any improper use of memory there.

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

#3


32  

You should never use retainCount for anything, with or without ARC.

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

When to use -retainCount?

什么时候使用-retainCount?

#4


15  

Use Instruments and locate the object you want to track by searching for the class name or pointer address if you have it while in in "Objects List".

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

When you have located it, hit the disclosure arrow on the instance. This brings you to a history view for retains and relases.

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

If you expand the right side detail view you will also see the callstack for each retain/release.

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

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

#5


3  

I believe the only way is to profile your application using the Allocations instrument. You will need to click on the info descriptor (the 'i' next to Allocation in the left pane) and click on "Record Reference Counts". You can then profile your app and do a search for the specific class you're looking to inspect. From there you can find the retain count in the Extended Detail pane for each instance of the class.

我认为唯一的方法是使用Allocations工具分析您的应用程序。您需要单击信息描述符(左侧窗格中“分配”旁边的“i”),然后单击“记录参考计数”。然后,您可以对您的应用进行概要分析,并搜索您要检查的特定类。从那里,您可以在“扩展详细信息”窗格中找到该类的每个实例的保留计数。

You can also do this using Leaks as well (since I believe it's a variation of the Allocations instrument).

您也可以使用Leaks执行此操作(因为我认为它是Allocations工具的变体)。

#6


1  

Get the object's retainCount?

获取对象的retainCount?

You can just make a breakpoint and input the command below to get the object's retainCount

您可以创建一个断点并输入以下命令来获取对象的retainCount

po object.retainCount

#7


0  

You don't. Apple say you don't need to as ARC will handle it for you.

你没有。 Apple说你不需要,因为ARC会为你处理它。