为啥 __weak 变量未在自动释放池中注册?
Posted
技术标签:
【中文标题】为啥 __weak 变量未在自动释放池中注册?【英文标题】:Why __weak variable not registered in autorelease pool?为什么 __weak 变量未在自动释放池中注册? 【发布时间】:2017-11-20 09:32:27 【问题描述】:id obj = [[NSObject alloc] init];
@autoreleasepool
id __weak weakObj = obj;
_objc_autoreleasePoolPrint();
NSLog(@"%@",[weakObj class]);
_objc_autoreleasePoolPrint();
运行上面的代码后,我在打印池时得到了意想不到的结果:
objc[22671]: [0x7ff544817858] ################ POOL 0x7ff544817858
objc[22671]: ##############
我找不到在autoreleasepool
中注册的对象。为什么?
【问题讨论】:
weakObj
只是对obj
的引用,obj
是在自动释放池之外分配的
@Paulw11 感谢您的关注!我将obj分配在自动释放池中。但我得到了相同的结果。
【参考方案1】:
我认为您误解了自动释放池是什么。它是一个对象集合,当池耗尽时(最常见于事件循环结束时)将收到release
消息。它不是将“通过某种方式自动释放”的对象列表。 特别是此自动释放池将向对象发送release
消息(并且在任何给定时间可能有多个池)。
它与weak
毫无关系。 “弱”是变量(指针)的一个属性。 “自动释放”是发生在对象上的事情。对象可能会被多次自动释放(这是正常的)。
在手动内存管理中,这通常通过向对象发送-autorelease
来完成。这意味着“现在不要释放它;我仍然需要它,但是当当前的自动释放池耗尽时,释放它。”请注意,这并不意味着“摧毁它”。它只是意味着“将保留计数减少一”。这就是你所说的“我只关心这个对象直到事件循环结束”(这是一个非常非常普遍的说法)。
在 ARC 中,您不能直接调用 -autorelease
,但 ARC 在某些情况下仍会使用自动释放池。一种非常常见的方法是在返回之前调用objc_autoreleaseReturnValue()
。 (这不是您直接调用的东西。它是 ARC 在需要时自动注入的东西。)在某些情况下,objc_autoreleaseReturnValue()
仍然可能实际上将对象放在自动释放池中。编译器足够聪明,可以检测到许多可以避免池并提高性能的情况。在其他情况下,ARC 可能会注入自动释放,并且这些情况也有可能绕过池的优化。
请注意,一般情况下,您的应用不应该依赖此功能。 _objc_autoreleasePoolPrint()
是 Apple 内部函数,用于低级调试。某些东西是否在自动释放池中很大程度上取决于 ARC 实现细节和当前的编译器优化。
【讨论】:
【参考方案2】:obj
永远不会自动释放,因此它不会放置在自动释放池中。如果你想自动释放obj
,你必须调用-autorelease
,例如
@autoreleasepool
id obj = [[[NSObject alloc] init] autorelease];
// ...
请注意,-autorelease
在 ARC 代码中不可用。
【讨论】:
【参考方案3】:我从这个link 得到答案。
Apple LLVM 8.0.0 版(clang-800.0.42.1)的__weak 新实现不会延迟发布到autoreleasepool,而是直接使用objc_release。
【讨论】:
以上是关于为啥 __weak 变量未在自动释放池中注册?的主要内容,如果未能解决你的问题,请参考以下文章