一个NSObject对象占用多少内存
例如,定义如下代码
1 | NSObject *obj = [[NSObject alloc] init]; |
使用 clang -rewrite-objc filename.m -o filename.cpp
使用 xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.c -o main-arm64.cpp
将以上的代码转为 C++ 文件,找到定义 NSObject
结构体
1 | struct NSObject_IMPL { |
找到 Class
的定义
1 | typedef struct objc_class *Class; |
为一个结构体指针,而结构体指针在 Mac 64bit 环境中占用 8 个字节,所以 NSObject_IMPL
结构体只占用了 8 个字节
为了验证此结构体是否只申请了个 8 个字节,使用 malloc_size((__bridge const void *)(obj))
函数来确定
但此时的返回值却为 16 个字节,为了进一步验证申请的内存大小,可以使用内存进行探究
找到 obj 的内存地址为 0x100709980
,打开其地址所指向的位置
似乎验证了NSObject
的成员所占的空间为 8 个字节,但申请的内存为 16 个字节,多出的 8 个字节暂时未被利用
但以上的推理仅仅是猜想的验证,为了更加具有说服力,打开 Obj-C 源码进行探究
首先找到 NSObject.mm 文件,方法的索引依次为:
_objc_rootAllocWithZone
-> class_createInstance
-> _class_createInstanceFromZone
-> instanceSize
打开 instanceSize
方法
1 | size_t instanceSize(size_t extraBytes) { |
可以看到,当所申请的的字节数小于 16 时,系统自动会返回 16 个字节,因此得以验证
但如果结构体的大小超过了 16 字节系统将如何分配?
OC 的内存分配
例如下代码
1 | #import <malloc/malloc.h> |
增加结构体成员
1 | #import <malloc/malloc.h> |
如果修改结构体中的成员大小
1 | #import <malloc/malloc.h> |
第一段代码中,结构体仅需要 16 个字节,系统分配了 16 个字节
第一段代码中,结构体仅需要 24 个字节,系统分配了 32 个字节
第二段代码中,结构体仅需要 40 个字节,系统分配了 48 个字节
所以 OC 的内存分配会以 16 的倍数进行分配
且结构体成员占用的位置和 Windows 相同,但实际占用也就是通过 class_getInstanceSize()
返回的数值为最大的结构体成员大小的倍数,多余的空间使用 0 补齐
另外,根据推论 Xcode 默认使用 4 字节对齐