我可以使用[self retain]将对象本身保存在objective-c中吗?

时间:2011-03-23 02:57:40

标签: memory-leaks garbage-collection objective-c++ autorelease

我正在使用[self retain]来持有一个物体,并[自我释放]将它释放到其他地方。这有时非常方便。但这实际上是一个引用循环或死锁,大多数垃圾收集系统都是为了解决它。我想知道objective-c的自动释放池是否可以找到循环并通过在到达[self release]之前释放对象来给我惊喜。我的方式是否受到鼓励?我怎样才能确保垃圾收集(如果有的话)不会太聪明?

2 个答案:

答案 0 :(得分:3)

这种工作方式非常气馁。看起来你需要关于内存管理的一些指示。

理论上,只要对象有用,它就应该存在。可以很容易地发现有用的对象:它们直接在线程堆栈的某处引用,或者,如果您创建了所有对象的图形,则可以通过链接到线程堆栈上某处引用的对象的某个路径来访问它们。没有被引用的“自己”生活的对象是没有用的,因为没有线程可以到达它们以使它们执行某些操作。

这就是垃圾收集器的工作方式:它遍历您的对象图并收集每个未引用的对象。请注意,Objective-C并不总是垃圾收集,因此必须建立一些规则。这些是memory management guidelines for Cocoa

简而言之,它基于“所有权”的概念。当您查看对象的引用计数时,您会立即知道有多少其他对象依赖它。如果一个对象的引用计数为3,则意味着其他三个对象需要它才能正常工作(因此拥有它)。每次保留对象的引用(在极少数情况下除外),都应调用其retain方法。在删除引用之前,应调用其release方法。

关于对象的创建,还有一些其他重要的规则。当您调用alloccopymutableCopy时,您获得的对象的引用数为1.在这种情况下,它表示调用代码负责释放对象需要。当你返回对象的引用时,这可能会有问题:一旦你返回它,理论上你就不再需要了它,但如果你在它上面调用release,它就会被立即销毁!这是NSAutoreleasePool个对象的来源。通过在对象上调用autorelease,您放弃所有权(就像您调用了release),除了该引用不会立即被撤销:相反,它会被转移到NSAutoreleasePool,一旦收到release消息本身就会释放它。 (每当Cocoa框架回调某些代码时,您可以确信已经存在自动释放池。)

如果您没有在其上调用alloccopymutableCopy,也意味着您没有自己的对象;换句话说,如果您获得对此类对象的引用,则无需在其上调用release。如果您需要像往常一样保留此类对象,请在其上调用retain,然后在完成后调用release

现在,如果我们尝试将此逻辑应用于您的用例,它就会变得奇怪。对象不能在逻辑上拥有自己,因为它意味着它可以独立存储在内存中,而不会被线程引用。显然,如果你有机会自己调用release,这意味着你的一个方法正在被执行;因此,你必须有一个参考,所以你不应该首先retain自己。我不能用你给出的一些细节说出来,但你可能需要调查NSAutoreleasePool个对象。

答案 1 :(得分:1)

如果您正在使用保留/释放内存模型,那应该不是问题。什么都不会找你的[self retain]并且颠覆它。但是,如果您切换到使用垃圾收集,那么可能不是这种情况,其中-retain和-release都是no-ops。

Here's another thread on SO on the same topic.

我会重申这个答案,其中包括“压倒性的顽皮感”。这不是违法的,但除非有充分的理由,否则感觉就像一个糟糕的计划。如果没有别的,它似乎是偷偷摸摸的,而且在代码中从来都不好。请注意该线程中的警告使用-autorelease而不是-release。