我可以使用 [self keep] 将对象本身保存在 Objective-C 中吗?
我使用 [自我保留] 来保存对象本身,并使用 [自我释放] 在其他地方释放它。这有时非常方便。但这实际上是一个引用循环或死锁,大多数垃圾收集系统的目标都是解决这个问题。我想知道 Objective-C 的自动释放池是否可以找到循环,并在到达[自我释放]之前释放对象,从而给我带来惊喜。我的方式是否受到鼓励?我怎样才能确保垃圾收集(如果有的话)不会太智能?
I'm using [self retain] to hold an object itself, and [self release] to free it elsewhere. This is very convenient sometimes. But this is actually a reference-loop, or dead-lock, which most garbage-collection systems target to solve. I wonder if objective-c's autorelease pool may find the loops and give me surprises by release the object before reaching [self release]. Is my way encouraged or not? How can I ensure that the garbage-collection, if there, won't be too smart?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这种工作方式非常不受欢迎。看来您需要一些有关内存管理的指导。
理论上,一个物体只要有用,就应该存在。可以很容易地发现有用的对象:它们直接在线程堆栈上的某个位置引用,或者,如果您制作了所有对象的图表,则可以通过链接到线程堆栈上某处引用的对象的某些路径来访问它们。没有被引用而“独立”存在的对象是没有用的,因为没有线程可以访问它们来使它们执行某些操作。
这就是垃圾收集器的工作原理:它遍历对象图并收集每个未引用的对象。请注意,Objective-C 并不总是进行垃圾收集,因此必须建立一些规则。这些是 Cocoa 内存管理指南 。
简而言之,它基于“所有权”的概念。当您查看一个对象的引用计数时,您立即知道有多少其他对象依赖于它。如果一个对象的引用计数为 3,则意味着其他三个对象需要它才能正常工作(因此拥有它)。每次保留对对象的引用(极少数情况除外)时,都应该调用其
retain
方法。在删除引用之前,您应该调用其release
方法。关于对象的创建还有一些其他重要规则。当你调用
alloc
、copy
或mutableCopy
时,你得到的对象已经有一个引用计数为1。在这种情况下,它意味着调用代码负责在不需要对象时释放该对象。当您返回对对象的引用时,这可能会出现问题:理论上,一旦您返回它,您就不再需要它了,但是如果您对其调用release
,它将立即被销毁!这就是NSAutoreleasePool
对象发挥作用的地方。通过在对象上调用autorelease
,您放弃它的所有权(就像您调用释放
),除了引用不会立即撤销:相反,它被转移到NSAutoreleasePool
,一旦它收到release
消息本身就会释放它。 (每当 Cocoa 框架回调您的某些代码时,您都可以确信自动释放池已经存在。)这也意味着如果您没有调用
alloc
,则您不拥有对象,<对它们进行 code>copy 或mutableCopy
;换句话说,如果您获得了对此类对象的引用,则无需对其调用release
。如果您需要像往常一样保留这样的对象,请对其调用retain
,然后在完成后release
。现在,如果我们尝试将此逻辑应用到您的用例中,就会发现它很奇怪。对象在逻辑上不能拥有自己,因为这意味着它可以在内存中独立存在,而不被线程引用。显然,如果您有机会自己调用
release
,则意味着您的方法之一正在执行;因此,周围必须有一个参考资料,所以您一开始就不需要保留
自己。我真的不能用你提供的一些细节来说明,但你可能需要研究NSAutoreleasePool
对象。This way of working is very discouraged. It looks like you need some pointers on memory management.
Theoretically, an object should live as long as it is useful. Useful objects can easily be spotted: they are directly referenced somewhere on a thread stack, or, if you made a graph of all your objects, reachable through some path linked to an object referenced somewhere on a thread stack. Objects that live "by themselves", without being referenced, cannot be useful, since no thread can reach to them to make them perform something.
This is how a garbage collector works: it traverses your object graph and collects every unreferenced object. Mind you, Objective-C is not always garbage-collected, so some rules had to be established. These are the memory management guidelines for Cocoa.
In short, it is based over the concept of 'ownership'. When you look at the reference count of an object, you immediately know how many other objects depend on it. If an object has a reference count of 3, it means that three other objects need it to work properly (and thus own it). Every time you keep a reference to an object (except in rare conditions), you should call its
retain
method. And before you drop the reference, you should call itsrelease
method.There are some other importants rule regarding the creation of objects. When you call
alloc
,copy
ormutableCopy
, the object you get already has a refcount of 1. In this case, it means the calling code is responsible for releasing the object once it's not required. This can be problematic when you return references to objects: once you return it, in theory, you don't need it anymore, but if you callrelease
on it, it'll be destroyed right away! This is whereNSAutoreleasePool
objects come in. By callingautorelease
on an object, you give up ownership on it (as if you calledrelease
), except that the reference is not immediately revoked: instead, it is transferred to theNSAutoreleasePool
, that will release it once it receives therelease
message itself. (Whenever some of your code is called back by the Cocoa framework, you can be assured that an autorelease pool already exists.)It also means that you do not own objects if you did not call
alloc
,copy
ormutableCopy
on them; in other words, if you obtain a reference to such an object otherwise, you don't need to callrelease
on it. If you need to keep around such an object, as usual, callretain
on it, and thenrelease
when you're done.Now, if we try to apply this logic to your use case, it stands out as odd. An object cannot logically own itself, as it would mean that it can exist, standalone in memory, without being referenced by a thread. Obviously, if you have the occasion to call
release
on yourself, it means that one of your methods is being executed; therefore, there's gotta be a reference around for you, so you shouldn't need toretain
yourself in the first place. I can't really say with the few details you've given, but you probably need to look intoNSAutoreleasePool
objects.如果您使用保留/释放内存模型,那么这应该不是问题。没有什么会去寻找你的
[self keep]
并颠覆它。然而,如果您切换到使用垃圾收集,则情况可能并非如此,其中 -retain 和 -release 是无操作的。这是关于同一主题的另一个线程。
我想重申一下答案,其中包括“压倒性的恶心感”这句话。这并不违法,但除非有充分的理由,否则感觉像是一个糟糕的计划。如果不出意外的话,这看起来很狡猾,而且这在代码中从来都不是好事。请注意该线程中的警告,使用 -autorelease 而不是 -release。
If you're using the retain/release memory model, it shouldn't be a problem. Nothing will go looking for your
[self retain]
and subvert it. That may not be the case, however, if you ever switch over to using garbage collection, where -retain and -release are no-ops.Here's another thread on SO on the same topic.
I'd reiterate the answer that includes the phrase "overwhelming sense of ickyness." It's not illegal, but it feels like a poor plan unless there's a pretty strong reason. If nothing else, it seems sneaky, and that's never good in code. Do heed the warning in that thread to use -autorelease instead of -release.