手撕iOS底层04 -- OC对象占用内存分析

849 阅读2分钟

本章主要由结构体内存对齐到苹果的属性重排, 以及16字节对齐算法

0x00 -- 获取内存大小的三种方式

Person *person = [Person alloc];
person.name      = @"xxxxx";
person.nickName  = @"ddd";
NSLog(@"%@ - %lu - %lu - %lu",
      person,
      sizeof(person),
      class_getInstanceSize([Person class]),
      malloc_size((__bridge const void *)(person)));
// 输出 8 - 40 - 48

获取内存大小的三种方式:

  • sizeof(expression-or-type)

小提示 💡: sizeof的三种语法形式:

        int a = 10;
        size_t a1 = sizeof(a); // 4
        size_t a2 = sizeof a;  // 4
        size_t a3 = sizeof(int); // 4
        int *pa = &a; 
        size_t p1 = sizeof(pa); // 8
        size_t p2 = sizeof pa;  // 8
        size_t p3 = sizeof(int *); // 8

        NSObject *obj = [NSObject alloc] ; 
        size_t o1 = sizeof(obj); // 8
        size_t o2 = sizeof obj; // 8
        size_t o3 = sizeof(NSObject*);// 8

sizeof()是操作符,不是函数;其作用是返回一个对象或者类型所占的内存字节数。

基本数据类型int,char,double,float等这样简单内置数据类型,它们的大小和系统相关, 不同系统下取值也不一样。

如果是结构体,sizeof涉及到字节对齐的问题,根据计算机组成原理教导我们这样有助于加快计算机的取数速度,否则多话指令周期。让宽度为2的节本数据类型short等,都位于能被2整除的低智商;让宽度为4的基本数据类型int等,都位于能被4整除的地址上,以此类推, 这样,俩个数中间就可能需要加入填充的字节,所以整个结构体的sizeof值就增长了。

  • class_getInstanceSize 这个RuntimeAPI是获取cls这个类所创建实例对象实际占用的内存大小,也就是实例对象大小
size_t class_getInstanceSize(Class cls)
{
    if (!cls) return 0;
    return cls->alignedInstanceSize();
}

// Class's ivar size rounded up to a pointer-size boundary.
uint32_t alignedInstanceSize() const {
   	return word_align(unalignedInstanceSize());
}

#ifdef __LP64__
#   define WORD_SHIFT 3UL
#   define WORD_MASK 7UL
#   define WORD_BITS 64
#else
#   define WORD_SHIFT 2UL
#   define WORD_MASK 3UL
#   define WORD_BITS 32
#endif

static inline uint32_t word_align(uint32_t x) {
    return (x + WORD_MASK) & ~WORD_MASK;
}

通过源码可知道 class_getInstanceSize函数获取的的对象大小是8字节对齐。

这个函数依据对象内部的属性变化而变化;如果没有属性, 只继承了NSObject,则类的实例对象实际占用的内存大小是8

  • malloc_size

这个函数位于#import <malloc/malloc.h>头文件中,获取的是指针所指向内存大小

malloc_size是系统实际开辟的内存空间,class_getInstanceSize是实际占用的空间。

根据文章顶部代码实例1打印可验证。这个是由系统完成的,从上面的分析看得出, 实际占用和实际分配的大小是不一样的。 例如: 系统根据一定对齐算法为你这个对象开辟了32字节,但你这个Class类所创建的对象实际只占用16字节。就这么个意思。


欢迎大佬留言指正😄,码字不易,觉得好给个赞👍 有任何表达或者理解失误请留言交流;共同进步;