iOS底层学习笔记-day-1
前言-OC语法篇
我是一名iOS开发者, iOS底层 菜鸟的进阶之路30天。
问题
一个NSObject对象占用多少内存?
- 系统分配了16个字节给NSObject对象(通过malloc_size函数获得)
- 但NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数获得)
Objective-C的本质
- LLVM指令例子
- clang -rewrite-objc main.m -o main.cpp 生成c++文件
- xcrun -sdk iphones clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
- ps:
- // 什么平台的代码
// 不同平台支持的代码肯定是不一样
// Windows、mac、iOS
// 模拟器(i386)、32bit(armv7)、64bit(arm64)
struct NSObject_IMPL {
Class isa; // 8个字节
};
- 一个NSObject的所占大小
- 为什么,因为分配了16个字节给他,但是实际只是用到了8个字节,8个字节用来放isa指针
NSObejct *stu = [[NSObejct alloc] init];
00000000 // isa占用的大小为8个字节
0000000000000000
// 获得NSObject 实例对象 的 成员(ivar)变量 所占用的大小 >> 8
NSLog(@"%zd", class_getInstanceSize([NSObject class]));
// 获得obj指针所指向内存的大小 >> 16。 coreFoundation中规定的
// malloc 分配内存 malloc_size(const void *ptr)
NSLog(@"%zd", malloc_size((__bridge const void *)obj));
- LLDB编译器的指令
memory read 0x01230031 简写x ,x/ 3xg
memory write 0x01230031 9 //重写
- 内存例子的说明
- 例子1
struct NSObject_IMPL {
Class isa;
};
struct Student_IMPL {
struct NSObject_IMPL NSObject_IVARS;
int _no;
int _age;
};
struct Student_IMPL {
Class isa; //父类的isa指针,8个字节
int _no; //4个字节
int _age; //4个字节
};
Student *stu = [[Student alloc] init];
stu->_no = 4;
stu->_age = 5;
NSLog(@"%zd", class_getInstanceSize([Student class]));
NSLog(@"%zd", malloc_size((__bridge const void *)stu));
struct Student_IMPL *stuImpl = (__bridge struct Student_IMPL *)stu;//4
NSLog(@"no is %d, age is %d", stuImpl->_no, stuImpl->_age);//5
- 例子2
struct NSObject_IMPL {
Class isa;
};
struct Person_IMPL {
struct NSObject_IMPL NSObject_IVARS; // 8
int _age; // 4
}; // 16 内存对齐:结构体的大小必须是最大成员大小的倍数
struct Student_IMPL {
struct Person_IMPL Person_IVARS; // 16
int _no; // 4
}; // 16
- 例子3
#import <malloc/malloc.h>
struct MJPerson_IMPL {
struct NSObject_IMPL NSObject_IVARS;
int _age;
int _height;
int _no;
}; // 计算结构体大小,内存对齐,24
MJPerson *p = [[MJPerson alloc] init];
NSLog(@"%zd", sizeof(struct MJPerson_IMPL)); // 24
NSLog(@"%zd %zd",
class_getInstanceSize([MJPerson class]), // 24 //sizeof是一个宏运算符 == class_getInstanceSize是一个函数 返回这个对象正真需要的存储空间
malloc_size((__bridge const void *)(p))); // 32 //malloc_size 指针指向的空间,返回的是实际分配的
其实是32个内容因为malloc
- #deifne NANO_MAX_SIZE 256 // bullect_size{16,32,48,64}
- 所以为什么是32,是因为苹果也做了一次内存对齐,所以给的是16的倍数,让CPU访问的速度快一点,遵循苹果的访问规则
两个容易混淆的函数
- class_getInstanceSize
//创建一个实例对象,至少需要多少内存?
#import <objc/runtime.h>
class_getInstanceSize([NSObject class]);
- malloc_size
//创建一个实例对象,实际上分配了多少内存?
#import <malloc/malloc.h>
malloc_size((__bridge const void *)obj);