iOS 对象在内存中的分布

1、一个NSObject对象占用多少内存?

系统分配了16个字节给NSObject对象(通过malloc_size函数获得);
但NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数获得)。

相关知识点:

//将oc文件重写为cpp文件:
clang -rewrite-objc main.m -o main.cpp
//将oc文件重写为运行在 iphone 上面的架构为 arm64 的cpp文件:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
// NSObject 在 oc 头文件中的定义
@interface NSObject  {
    Class isa;
}
//对应的 C++ 的代码是:
struct NSObject_IMPL {
    Class isa;
};
//结论1: 可以看出,OC类的底层实现是C++的结构体。
//ps:  typedef struct objc_class *Class; 
//Class是一个结构体指针。

//猜测:指针在64位环境中占8个字节,因为一个 NSObject 对象只有一个成员为Class类型的isa,所以一个 NSObject 对象也占8个字节。
//验证:
//导入头文件:
#import 
#import 
NSObject *obj = [[NSObject alloc] init];
//获取 NSObject 类的实例对象的成员变量在内存中占用空间的大小 >> 8
NSLog(@"%zd",class_getInstanceSize([NSObject class]));
//获取指针obj 所指向的内存空间的大小 >> 16
NSLog(@"%zd",malloc_size((__bridge const void *)(obj)));

//为什么打印出来的结果不一样呢?
//通过 https://opensource.apple.com/tarballs/,查看苹果源码。苹果源码中 class_getInstanceSize的源码实现
size_t class_getInstanceSize(Class cls)
{
    if (!cls) return 0;
    return cls->alignedInstanceSize();
}
//alignedInstanceSize :苹果给的注释是:Class's ivar size rounded up to a pointer-size boundary。即成员变量的大小,也就是isa指针的大小。即在arm64环境中是占8个字节。
//allocWithZone源码
_objc_rootAllocWithZone(Class cls, malloc_zone_t *zone)
{
    id obj;

    if (fastpath(!zone)) {
        obj = class_createInstance(cls, 0);
    } else {
        obj = class_createInstanceFromZone(cls, 0, zone);
    }

    if (slowpath(!obj)) obj = _objc_callBadAllocHandler(cls);
    return obj;
}
_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone)
{
    void *bytes;
    size_t size;

    // Can't create something for nothing
    if (!cls) return nil;

    // Allocate and initialize
    size = cls->alignedInstanceSize() + extraBytes;

    // CF requires all objects be at least 16 bytes.
    if (size 

2、字节与十六进制、二进制的关系

一个字节是由两位16进制数组成。
十六进制一般用数字0到9和字母A到F(或a ~ f)表示,其中:A~F表示10~15,这些称作十六进制数字。
十六进制数转换在二进制数:把每一个十六进制转换成4位的二进制数,就得到一个二进制数。
十六进制数字与二进制数字的对应关系如下:
二进制 0000 对应十六进制 0
二进制 0001 对应十六进制 1
二进制 0010 对应十六进制 2
二进制 0011 对应十六进制 3
二进制 0100 对应十六进制 4
二进制 0101 对应十六进制 5
二进制 0110 对应十六进制 6
二进制 0111 对应十六进制 7
二进制 1000 对应十六进制 8
二进制 1001 对应十六进制 9
二进制 1010 对应十六进制 A
二进制 1011 对应十六进制 B
二进制 1100 对应十六进制 C
二进制 1101 对应十六进制 D
二进制 1110 对应十六进制 E
二进制 1111 对应十六进制 F
因此,1个16进制位对应4个二进制位,2个16进制位对应8个二进制数位,即1个字节。

image.png

如上图所示,红框代表一个字节,蓝框代表16个字节。

3、常用LLDB指令

print、p : 打印
po:打印对象

读取内存
memory read/数量格式字节数 内存地址
x/数量格式字节数 内存地址
x/3xw 内存地址

格式
x是16进制,f是浮点,d是10进制

字节大小
b:byte 1字节,h: half word 2字节
w:word 4字节,g: giant word 8字节

改写内存
memory write 内存地址 修改值
memory write 内存地址 8

4、c++ 与 oc 代码互转

struct Student_IMPL {
    Class isa;
    int _no;
    int _age;
};

@interface Student : NSObject {
    @public
    int _no;
    int _age;
}

@end

@implementation Student

@end

typedef struct objc_class *Class;

int main(int argc, char * argv[]) {
    
    @autoreleasepool {
        Student *stu = [[Student alloc] init];
        stu->_no = 4;
        stu->_age = 5;
        
        struct Student_IMPL *stuIMPL = (__bridge struct Student_IMPL *)stu;
        NSLog(@"no is %d,age is %d",stuIMPL->_no,stuIMPL->_age);
        
    }
    return 0;
}

【信息由网络或者个人提供,如有涉及版权请联系COOY资源网邮箱处理】

© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容