iOS底层系列之<1>--OC对象本质

1、OC的对象、类主要是C\C++的什么数据结构实现的?

  • 结构体

2、把OC代码转换成c++代码

  • iPhone架构分类:
模拟器i386架构
32bit真机armv7
64bit真机arm64
  • 指令:
直接转换:
 clang -rewrite-objc main.m -o main.cpp
iPhone平台转换:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp
  • 在main.cpp文件中,搜索NSObject_IMPL可以发现
struct NSObject_IMPL {
   Class isa; // 指针 8个字节
};
  • 内存大小
// 先导入头文件如下
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <malloc/malloc.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSObject *obj = [[NSObject alloc] init];
        
        // 获取NSObject类的实例对象的大小
        NSLog(@"实例对象的大小-%zd",class_getInstanceSize([NSObject class]));
        
        // 获取obj指针指向内存的大小
        NSLog(@"指针指向内存的大小-%zd",malloc_size((__bridge const void *)(obj)));
        
        NSLog(@"Hello, World!");
        
        /**打印结果如下:
         2021-12-23 19:31:15.893600+0800 01-oc本质[1512:18220] 实例对象的大小-8
         2021-12-23 19:31:15.893932+0800 01-oc本质[1512:18220] 指针指向内存的大小-16
         2021-12-23 19:31:15.893962+0800 01-oc本质[1512:18220] Hello, World!
         */
    }
    return 0;
}

那么内存的大小到底是多少呢?

  • 下载最新的苹果objc开源代码:https://opensource.apple.com/tarballs/objc4/
  • 全局搜索“size_t instanceSize”,可以看到这段源码
size_t instanceSize(size_t extraBytes) {
       size_t size = alignedInstanceSize() + extraBytes;
       // CF requires all objects be at least 16 bytes.
       // 注释大概意思是说,所有的对象最少要16个字节
       if (size < 16) size = 16;
       return size;
   }

**

问题:一个NSObject对象占用多少内存?
1、系统分配了16个字节NSObject对象
2、但是NSObject对象内部只使用了8个字节的空间

**

3、进一步窥探内存细节

  • 运行XCode,打断点

  • 设置-- Debug–> Debug Workflow --> Always Show Disassembly

  • 把对象地址打印出来,可以发现只有前面8个字节有内容,后面8个字节是空的

在这里插入图片描述

4、通过LLDB指令窥探细节

  • 常用LLDB指令
  • (大小端模式)苹果一般是小端模式:
2019 = 2*10^3+0*10^2+1*10^1+9*10^0
可以称高位对应的权重(10^3)大,低位对应的权重小。

小端就是先存储权重小的,大端就是先存储权重大的
举例:0x1234
不要记忆高地址,低地址,看下图
(或者记住:正常人写阿拉伯数字就是大端模式,从左往右开始写)
从左到右,地址从低到高

小端模式4321
大端模式1234
低地址高地址


-- print、p : 打印
-- po : 打印对象
-- 读取内存
  1、mermory read/数量+格式+字节数  内存地址
      例如:x/3xw 0x10010
      
       修改内存中的值
       memory write 内存地址 数值
       mermory write 0x00000010 10
/*
(lldb) memory read 0x0000000100605230
0x100605230: 89 50 60 80 ff ff 1d 01 00 00 00 00 00 00 00 00  .P`.............
0x100605240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
(lldb) memory write 0x0000000100605234 7 
(lldb) memory read 0x0000000100605230
0x100605230: 89 50 60 80 07 ff 1d 01 00 00 00 00 00 00 00 00  .P`.............
0x100605240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

可以看到内存值由 89 50 60 80 ff
改为了          89 50 60 80 07 
*/
  2、格式:x 16进制, f 浮点数, d 10进制
  3、字节大小:
  		b: byte        1字节
  		h: half word   2字节
  		w: word        4字节
  		g: giant word  8字节
  		
/*  打印结果
(lldb) p obj
(NSObject *) $1 = 0x0000000100605230
(lldb) po obj
<NSObject: 0x100605230>

(lldb) memory read 0x0000000100605230
0x100605230: 89 50 60 80 ff ff 1d 01 00 00 00 00 00 00 00 00  .P`.............
0x100605240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
(lldb) x 0x0000000100605230
0x100605230: 89 50 60 80 ff ff 1d 01 00 00 00 00 00 00 00 00  .P`.............
0x100605240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
(lldb) x/3xg 0x0000000100605230
0x100605230: 0x011dffff80605089 0x0000000000000000
0x100605240: 0x0000000000000000
(lldb) x/3xh 0x0000000100605230
0x100605230: 0x5089 0x8060 0xffff
(lldb) x/3xw 0x0000000100605230
0x100605230: 0x80605089 0x011dffff 0x00000000
(lldb) x/3xb 0x0000000100605230
0x100605230: 0x89 0x50 0x60
(lldb) x/4xw 0x0000000100605230
0x100605230: 0x80605089 0x011dffff 0x00000000 0x00000000
(lldb) x/4dw 0x0000000100605230
0x100605230: -2141171575
0x100605234: 18743295
0x100605238: 0
0x10060523c: 0
(lldb) x/4fw 0x0000000100605230
0x100605230: -8.8450982E-39
0x100605234: 2.9020014E-38
0x100605238: 0
0x10060523c: 0
(lldb) 
*/

5、注意的地方

定义这样一个类
@interface Student : NSObject
{
    @public
    int _no;
    int _age;
    int _height;
}
@end

@implementation Student


@end


int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"%zd", sizeof(struct Student_IMPL)); // 打印结果24
        
        Student *stu = [[Student alloc] init];
        
        NSLog(@"%zd", class_getInstanceSize([Student class])); // 打印结果24
        NSLog(@"%zd", malloc_size((__bridge const void *)(stu))); // 打印结果32
    }
    return 0;
}
  • 分配给stu对象的内存是32,实际使用的是24
  • 因为在iOS系统里面,给对象分配的最少内存单位是16,所以说,对象的内存大小是16的倍数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值