1. 在编译器中查看,有两种查看Size的方法
- 方式一:
class_getInstanceSize([NSObject class])
- 方式二:
malloc_size((__bridge const void *)(obj))
- 编译器中运行结果如下:
- 发现
class_getInstanceSize
和malloc_size
方法得到的结果不一样。
- 发现
2. 那究竟哪个才是NSObject实际占用内存的大小呢?
- 查看OC源码一探究竟
- 登陆苹果开源网站:
https://opensource.apple.com/tarballs/
,搜索objc
- 找到最新的OC源码(数字最大的):
- 下载并打开项目,在OC源码项目中搜索
class_getInstanceSize
,找到了其实现:
- 继续往下查看,发现该方法的注释:
- 大致意思为:返回了这个类中的成员变量所占用的大小。
- 登陆苹果开源网站:
- 总结:
class_getInstanceSize([NSObject class])
的意思是:获得NSObject实例对象的成员变量所占用的大小 ,并非获取NSObject所占用的大小。malloc_size((__bridge const void *)(obj))
的意思是:获得obj指针所指向内存的大小。- 结论:所以一个NSObject对象占用16个字节,而真正利用起来的只有8个字节。如下图所示:
3. 为什么会这样呢?
- 还是从源码中找线索,寻找
alloc
的源码,为了缩小搜索范围,我们知道alloc
的本质是allocWithZone
,所以我们在源码中搜索allocWithZone
。找到NSObject.mm文件中的方法:
- 继续往下搜索
_objc_rootAllocWithZone
- 再往下搜索
_class_createInstanceFromZone
,发现了底层调用了calloc
方法,并指定了一个size,这个size是通过instanceSize()
方法获取的
- 搜索
instanceSize(
,终于发现了真相:
if (size < 16) size = 16;
,原来底层判断了一个对象至少需要分配16个字节,如果小于16则强制分配16字节给这个对象。 - 这样我们就可以理解,为什么NSObject对象只有一个isa成员变量,只占用了8个字节,但为什么NSObject对象确会占用16字节了。
4. 总结:
- 系统分配了16个字节给NSObject对象(通过
malloc_size
函数获得) - 但NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过
class_getInstanceSize
函数获得)
5. 补充:用Xcode调试模式,窥探NSObject的内存
- 进入断点模式
- 进入
Debug
->Debug Workflow
->View Memory
模式
- 将obj的地址,放入Address中,回车进行查看:
- 我们可以发现,后8个字节全是0,说明其中并没有存放东西,所以也印证了我们之前的结论。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END