ChenYilong / iOSInterviewQuestions

iOS interview questions;iOS面试题集锦(附答案)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

第34题 答案 疑问

yupliang opened this issue · comments

所有 autorelease 的对象,在出了作用域之后,会被自动添加到最近创建的自动释放池中

为什么需要出作用域后加入,而不是[obj autorelease]调用的时候?

autorelease的作用在于延长对象生命周期,保证对象在跨越“方法调用边界”后存活一段时间,在清空最外层自动释放池时执行此对象的释放操作。出于这个目的,我个人觉得之所以在需要出作用域后将对象加入自动释放池,这样能够确保对象被加入到调用函数所在的自动释放池中。如果是在[obj autorelease]调用时将对象加入最近创建的自动释放池,那么一下这种情况就会让autorelease失去了意义:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

id obj = [NSObject new];

return [obj autorelease];

[pool  release];

那句出了作用域是错的。这例子。。

我觉得作者所指出的 "所有 autorelease 的对象" 并不是指的 [obj autorelease] 这种情况,它代表的是在ARC 内存管理下的对象,当出了作用域、autoreleasepool 和 runloop 循环后,这些对象将会进行 relase,当引用计数器为0的时候,对象会被添加到自动释放池(说白了就是将该内存地址标记后放内存池),对象什么时候释放,这得看具体策略,有即时释放和延时释放,不过为了尽量少的减少内存抖动的发生,一般采用延时释放,也就是过了一定时间后释放这些标记的地址的内存块。

'当引用计数器为0的时候,对象会被添加到自动释放池', 基本内存管理原则还是需要的啊,引用计数为0,对象要被释放了。

对不起,不太理解你的意思,我尝试回答一下你的理解:其实引用计数器为0的时候,只是OC层面的地址标记,并不代表内存就得马上是释放,你也可以试试,将对象 relase 到 0 后,再访问其内存,只要内存池没有释放,内存依然还是在的,内存什么时候释放,并不是 OC 说了算,这是跟程序所在的编译器中的内存分配器的策略相关的。

在我看来,内存跟对象是毫无关系的,这是面向OOP**强加的一个概念,一个所谓的对象,就是一组虚拟内存块而已

将对象 relase 到 0 后,再访问其内存,只要内存池没有释放。针对这句,你不妨贴一下代码。

这位同学,你想要的都在这里 https://stackoverflow.com/questions/25609945/why-does-mstats-and-malloc-zone-statistics-not-show-recovered-memory-after-free 。 如果还不懂,建议补一下计算机基础知识,可以先看一下比较著名的CSAPP(深入理解计算机系统)。工作比较忙,可能比较晚回复,见谅

好的,谢谢。@Abson

commented

@yupliang 我怎么觉得 Abson 说的不对,在《iOS 与 OS X 多线程管理》这本书里描述的 autoreleasepool 只是一个对象持有者,导致引用计数+1而已,引用计数为0,对象会立马调用 dealloc 进行释放,虽然内存数据很可能还在,但是对这片内存的访问已经非法,因为随时可能被覆写