先来看一个面试题

我们来用clang编译器转起c++ 看看.
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o testMain.c++
打开C++文件发现其生成的对象转成如下图所示


NSObject_IMPL 其实就是NSObject implementation 对象生成.
发现其实际上一个结构体.那么Class又是什么?点进去发现是一个指向结构体的指针.

那么一个指针 在64位系统下占用是8个字节,
导入Runtime
Person *object = [[Person alloc]init];
NSLog(@"%zd", class_getInstanceSize([object class]));
输出结果是8.

我们再来看另一个函数导入 malloc 头文件

这2者有什么区别?我们下载runtime源码试分析,原来
class_getInstanceSize
是返回成员变量所占用的大小
接下来看
alloc
实现,alloc底层起始调用的是allocWithZone
通过源码发现其最终调用的是
原来
CoreFoudation
框架规定所有的对象至少16个字节.那么回答上面那道面试题:
- 系统分配了16个字节但是利用的只有8个字节.
接下来我们用Xcode来验证一下是不是16个字节.断点调试点击感叹号,输出object的地址,接下来Debug
-->view Memory

- 1个字节包含8个2进制位
- 1个16进制可表示4个2进制为
- 2个16进制可表示1个字节
image.png
可以看到前面8个字节是存放isa
的后面8个字节都是00 ,在后面又是其他东西的内存.我们其实可以用LLDB的po命令
也能验证.
image.png
扩展:- x/3xg - x 就是memory read简称
- 3 表示输出数量
- x 表示16进制 (x:16 f:浮点 d:十进制)
- g 字节数 (b:1字节 h:2字节 w:4字节 g:8字节)
memory write
修改内存中的值:例如修改第六位的值为10
image.png
假如person增加2个成员变量又占多少内存了?


计算机常识:
内存对齐:结构体的大小必须是最大成员大小的倍数
所有就算没有oc规定的至少16个字节,它也占16个字节.

当成员变量变成3个的时候呢?

这里应该是20 由于要是8的倍数 实际上是24,接下来看输出.

实际所分配的内存是32?为什么会这样?通过分析苹果开源代码 libmalloc,这里可以参考这篇文章 iOS内存基本原理
-
在64环境下,malloc优先考虑nano malloc,负责对256B以下小内存分配,单位是16B。也就是说,是16的倍数,这是系统规定的有些类似内存对齐,那么上面24显然不符合,所以系统分配了32B.
image.png
-
总结:
-class_getInstanceSize
返回的是结构体所占用的大小.
-malloc_size
返回的是实际系统给分配的内存大小.
网友评论