NSObject 占用内存大小

我们平时编写的Objective-C代码本质上其实都是通过底层的C\C++代码的实现的,而C\C++代码会转变成汇编语言,最终被计算机解释成能识别的机器语言。

image

正因为 OC底层是通过 C\C++语言实现,故我们可以通过 clang编译器将 OC代码转换成 C\C++语言

  xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 输出的cpp文件

如果需要链接其他框架,使用-framework参数。比如-framework UIKit

通过上述转换之后很容易找到 NSObject 类的真正实现

struct NSObject_IMPL {
    Class isa;
 }

我们发现在NSObject_IMPL中只有一个名为 isa 的 Class 实例。这个Class又是一个什么东西呢?

/// An opaque type that represents an 
 typedef struct objc_class *Class;

发现 Class 实际上是一个指向 objc_class 的结构体指针,其实NSObject最终是一个指向结构体 objc_class的名为isa的结构体指针。

接下来我们通过Runtime中 的class_getInstanceSize来查看下NSObject这个类的实例对象的成员变量的大小

NSObject *obj = [[NSObject alloc] init];
NSLog(@"NSObject实例对象的成员变量所占用的大小为:%zd",class_getInstanceSize([NSObject class]));
通过控制台打印可以发现:
NSObject实例对象的成员变量所占用的大小为:8

综上所述:NSObject 中的成员变量isa占 8 个字节的大小。

我们也可以通过objc4源码得出此结论:

class_getInstanceSize在源码中实现如下:

NSObject 占用内存大小_第1张图片
image.png

image.png

Class's ivar size rounded up to a pointer-size boundary.
一个类的所有成员变量所占用的空间。

那么 OC 中一个 NSObject 对象真的是占8个字节嘛?

接下来我们再通过malloc_size(const void *ptr) 来看下NSObject这个类所占的内存大小

NSObject *obj = [[NSObject alloc] init];
NSLog(@"obj指针所指向内存大小为:%zd", malloc_size((__bridge const void *)obj));
通过控制台打印可以发现:
obj指针所指向内存大小为:16

为什么这次通过malloc_size(const void *ptr)打印出来的字节数是16而不是8?。

我们知道在OC的对象实例中,真正给对象分配内存的方法是:

+ (instancetype)allocWithZone:(struct _NSZone *)zone OBJC_SWIFT_UNAVAILABLE("use object initializers instead");

allocWithZone 在objc4源码又是如何实现的呢?

image.png

NSObject 占用内存大小_第2张图片
image.png

NSObject 占用内存大小_第3张图片
image.png

虽然系统分配了16个字节给NSObject对象,但是通过class_getInstanceSize所知NSObject内部
真正利用的只有8个字节,我们接下来继续研究:

通过Debug->Debug Workflow->View Memory查看NSObject对象所分配的内存,如图:

NSObject 占用内存大小_第4张图片
image.png

综上所述:NSObject对象至少分配16个字节,但是被系统真正利用的只有8个字节

你可能感兴趣的:(NSObject 占用内存大小)