内存对齐探上一探

2020-09-10  本文已影响0人  灰溜溜的小王子

写在前面:

了解下lldb调试命令:

po                 打印信息
p                 打印详细的信息
bt                 打出堆
register read      读取寄存器
x                  读取内存段
x/4gx              读取4段内存段

说到内存对齐这个玩意儿,说实话一脸懵逼
光这个三个玩意儿(如何获取内存的大小)够喝一壶:

1.sizeof()
2.class_getInstanceSize()
3.malloc_size()
一块看看是个啥吧,创建一个类,属性如下
@interface PHPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) long height;
@end
· #import <objc/runtime.h>
· #import <malloc/malloc.h>

我的理解是(个人理解有待验证):
sizeof:是person这个指针所isa需要的内存大小8字节固定
class_getInstanceSize:存储这个PHPerson类所需要的空间大小
malloc_size:系统分配的空间大小(内存对齐原则16字节)
为了验证咱的猜测,添加断点

注释掉heigh类型为long的属性之后打印如图: image.png
分配情况二

注释掉所有属性之后


image
分配情况三 属性占用字节数

这下懵了:

size_t instanceSize(size_t extraBytes) const {
        if (fastpath(cache.hasFastInstanceSize(extraBytes))) {
            return cache.fastInstanceSize(extraBytes);
        }

        size_t size = alignedInstanceSize() + extraBytes;
        // CF requires all objects be at least 16 bytes.
        if (size < 16) size = 16;//看见没有这是重点额,不够十六字节就分配十六个字节大小
        return size;
    }

注意:NSObject对象内部只使用了8个字节的空间(可以通过class_getInstanceSize函数获得)

class_getInstanceSize(Class _Nullable cls) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);


size_t class_getInstanceSize(Class cls)
{
    if (!cls) return 0;
    return cls->alignedInstanceSize();
}

 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) {
//此时WORD_MASK是64位下的WORD_MASK 7UL 即8字节对齐
    return (x + WORD_MASK) & ~WORD_MASK;
}

通过一个例子先了解下字节对齐,下边再探

struct object {
    int a; // 4
    NSString *b; // 8
    int c; // 4
    char d; // 1
};
  • 未对齐 - 对齐

打开PHPerson.h中所有属性变为成员变量方便分析,此时cd到当前工程目录下通过xcrun -sdk iphonesimulator clang -rewrite-objc main.mmain.m编译成cpp的c++文件如图

image.png
@interface PHPerson : NSObject{
    NSString *name;
    NSString *nickName;
    int age;
    long height;
}

编译后可以看到PHPerson对象其实是个结构体指针,内存对齐可以参考上方结构体object


struct PHPerson_IMPL {
      //指针对象,占用8字节
    struct NSObject_IMPL NSObject_IVARS;
    NSString *name;//字节8                         0-7
    NSString *nickName;//8字节                   8-15
    int age;//4字节                             16-20  补齐21-23
    long height;//8字节                        24-31
};  共需要8+32  字节数

参照:关于NSObject对象的内存布局

上一篇 下一篇

猜你喜欢

热点阅读