OC对象的本质

iOS-对象的本质-一个OC对象占多少内存 我们平常敲的Objective-C代码,底层实现其实是C/C++代码.那么一个OC对象占用多少内存. iOS开发中Objective-C和swift用的是Clang/LLVM来编译的. 使用的clang编译器编译成cpp,xcodebuild负责将OC/Swift工程编译成xxx.app,xcrun负责给xxx.app签名并打包成xxx.ipa #import <Foundation... 阅读详情

OC和C_C++OC和C_C++

  • 一个NSObject对象占多少内存
NSObject *person = [[NSObject alloc] init];

也就是说person指针指向的这段内存空间,占有多少内存空间?
要想知道他在内存中占有多少空间,就要知道他在内存是怎么布局的,在内存中包含哪些内容,搞清楚这段代码的本质是什么,
我们平时编写的OC代码,底层实现其实都是C\C++代码,

截屏2020-10-18 下午6.45.28.png

编译器会将C\C++转成汇编,然后再转成机器语言运行
所以Objective-C的面向对象都是基于C\C++的数据结构实现的
思考:Objective-C的对象、类主要是基于C\C++的什么数据结构实现的?
结构体

将Objective-C代码转换为C\C++代码

可以安装一个gotocell可以快速定位到终端
代码之后之间的转换肯定是编译器编译的结果,所以要用编译器相关的工具,这里使用使用的clang,clang是xcode内置的编译器llvm的编译器前端clang -rewrite-objc main.m -o main.cpp
因为我们生成文件是c和c++都有的所有最好生成CPP文件(c plus plus),
不建议直接用上面的来直接转,因为编译也要看我们要转成什么平台的代码,不同平台支持的代码肯定是不一样的,因为我们的代码会转成汇编,会变得运行要根据硬件不同来运行,所以我们只希望生成IOS平台来生成,
模拟器(i386) 32bit(armv7),64bit(arm64)xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 输出的CPP文件
没有指定架构的生成文件的大小3.5M,指定之后只有1M多,

截屏2020-10-18 下午7.11.04.png

NSObject对象的内存本质

我们上面生成文件,就是想看看 [[NSObject alloc] init];他的本质是什么,
我们再相关的文件中可以找到NSObject_IMPL

struct NSObject_IMPL {
    Class isa;
};

如果将我们cpp拖进xcode项目,编译会报错,因为cpp是临时生成的,还有一个就是cpp文件也有一个main函数,一个程序只能有一个main函数,所有也会出错,
可以再Xcode的编译文件中,将cpp去掉,

截屏2020-10-18 下午7.18.34.png

NSObject_IMPL他的意思就是NSObject Implementation,也就是一个NSObject的底层实现,
如果我们直接通过Xcode点进去看一下NSObject的实现可以发现

@interface NSObject <NSObject> {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
    Class isa  OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop
}
@end
简化成
@interface NSObject {
    Class isa  ;
}
@end

OC的类他的底层实现就是结构体,C\C++的结构体支撑的OC的面向对象

  • 问题一个OC对象内存中是如何布局的?
    NSObject的底层实现,头文件里面

    截屏2020-10-18 下午7.26.57.png

    底层实现

    截屏2020-10-18 下午7.34.12.png

    isa 我们可以按进去看一下,他的类型是这个样子,是一个指向结构体的指针
typedef struct objc_class *Class;

既然isa是一个指针那么他在64bit的机器占据8个字节,32bit4个字节,
所以alloc相当于给右边的结构体分配存储空间,分配完成之后,会又一个指针,指向我们的分配的这段空间,假设我们分配的空间isa的地址0x100400110

截屏2020-10-18 下午7.40.03.png

class_getInstanceSize、malloc_size.

一个NSObject对象占多少内存?
根据我们上面代码分析,我们可能会觉得一个NSObject占用8个字节的内存,实际上不是,实际上是16个字节,但是他利用起来的只有8个字节的大小,我们可以用runtime来验证一下,class_getInstanceSize用来获取一个类的实力对象的大小,实例就是我们通过alloc出来的具体对象,malloc_size获得指针所指向的内存大小

//获得NSObject的实例对象的成员变量所占用的大小
       NSLog(@"%zu大小", class_getInstanceSize([NSObject class]));//8字节
       //获得指针所指向的内存大小
       NSLog(@"%zd", malloc_size(CFBridgingRetain(person)));// 16字节

苹果开源网站 opensource.apple.com->objc(https://opensource.apple.com/tarballs/objc4/)找到最新的进行下载
解压之后我们直接打开项目,搜索class_getInstanceSize查看源码发现,他会调用一个

截屏2020-10-18 下午8.06.33.png

返回就是实例对象的成员变量的大小
实际内存中
截屏2020-10-18 下午8.10.15.png

面试题回答

我们还是回到IOS的源码
通过alloc查看他是否真的是占用了16个字节,实际上调用了allocWithZone

截屏2020-10-18 下午8.14.56.png

在它里面调用了calloc函数,这里需要传一个size参数,

size

所以一旦发现小于16他就会分配16个字节,因为他规定所有的对象最低是16个字节,这是corefoundation硬性规定的

  • 一个NSObject对象占多少内存?

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

窥探NSObject的内存

我们可以从另一个角度去验证他是否占了16个字节的内存,Xcode工具,打断点,查看对象的地址

截屏2020-10-18 下午8.32.19.png

然后通过debug->debugworkflow->view memory

截屏2020-10-18 下午8.33.49.png

因为内存使用的是16进制,所以两位占一个字节,
通过内存图我们可以看出来我们的对象在内存的分布形式,有颜色的部分就是我们的NSObject的内存分布,可以看出来,他只是用了前8个字节

内存分布16.png

我们也可以通过打断点之后使用 (lldb)调试器来进行调试

lldb常用的指令print、p:打印

po:打印对象
内存读取memory read/数量格式字节数 内存地址
x/数量格式字节数 内存地址
x/3xw 0x10010

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

    字节大小
     b:byte 1字节,h:half word 2字节
     w:word 4字节,g:giant word 8字节
  • 修改内存中的值memory write 内存地址 数值
    memory write 0x0000010 10

使用例子

截屏2020-10-18 下午8.55.29.png

Student的本质

@interface Student : NSObject{
    @public
    int _no; //4字节
    int _age;//4字节
    
}
@end

@implementation Student
@end

通过终端生成C++代码

struct NSObject_IMPL
{
    Class isa; //8字节
};
struct Student_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
    int _no;
    int _age;
};

我们写的创建一个对象的方法

Student *student = [[Student alloc] init];
        NSLog(@"%zd", class_getInstanceSize([student class]));//16
        NSLog(@"%zd", malloc_size((__bridge const void *)(student)));//16
        student->_no = 12;
        student->_age = 15;

在内存中的分布图其实是这个样子的

student对象的内存结构

因为结构体的地址就是第一个成员变量的地址,所以Student的地址就是isa的地址,内存分布是连续的,接下来的4个字节存储的_no的值,再4个是age的值,
我们可以强制将student指针,转成结构体类型

struct Student_IMPL *stu = (__bridge struct Student_IMPL *)student;
        NSLog(@"no=%d,age=%d", stu->_no,stu->_age);//no=12,age=15

也可以正常的访问,进一步说明了,他本质上就是这个结构体类型

Student的内存结构

CPU从内存读取数据的方式分为大端和小端模式,IOS就是小端模式,读数据会从小的地址开始,所以他的四个字节是 04 00 00 00,

更复杂的集成模式

//Person
@interface Person:NSObject
{
    @public
    int _no;
}
@end

@implementation Person

@end
//Student
@interface Student:Person
{
    @public
    int _age;
}
@end
  • 思考:一个Person对象、一个Student对象占用多少内存空间?

    截屏2020-10-19 上午11.12.49.png

    答案 都是16个字节

内存对其,结构的内存大小,必须是最大成员变量的倍数,

因为Person占居了16个字节,但是最后面的4个字节是空的所以当Student继承了之后,会把自己age放到最后面的4个空字节上面,因此,student还是占据了16个字节,

如果我们增加一个int类型的成员变量,就会占32,

@interface Student:Person //16
{
    @public
    int _age;//4
    int _weight;//4
}
@end

我们通过alloc init出来的实例对象,是不会存储方法的,他只存有成员变量的值,因为方法在内存中指存在一份就够了,不需要每个实例都存一份

回答疑问

计算内存地址,就是一个个的往后数,

12-内存分布注意点

@interface Dog : NSObject
{
    //struct NSObject_IMPL NSObject_IVARS;//8个字节
    int _no;//4
    int _age;//4
    int _height;//4
} //理论上他在内存的大小是24字节
NSLog(@"%zd", class_getInstanceSize([dog class]));//24
NSLog(@"%zd", malloc_size((__bridge const void *)(dog)));//32

因为malloc_size结果是32 ,这个是他在内存中被分配的大小,因为他内存对其的单位是16,所以malloc的空间必须是16的倍数.

13-alloc的size分析

在calloc函数中分配内存的时候,传入的size确实就是实力对象的内存大小,24,但是底层内部的实现,会将这个歌内存惊醒对其计算,返回一个对其之后的size在进行实际分配,对其之后就是32

详解在linux上安装vpn客户端 阅读详情

相关推荐

C# NX二次开发:两种过滤器设置方案的实战解析与场景适配

本文深入解析C# NX二次开发中的两种过滤器设置方案:AddFilterHandler回调与MaskTriple属性设置。通过实战案例对比其性能差异与适用场景,帮助开发者根据需求选择最优方案,提升NX插件开发效率与交互体验。特别针对BlockStyler集成场景提供专业建议,是NX二次开发者的实用指南。

weixin_33739646的博客 844

OC底层-OC对象的本质

OC对象的本质 1.1、NSobject 对象底层实际是有一个isa指针的NSObject_IMPL结构体; 1.2、一个object对象会分配的到多少内存? 大小16个字节 ,可以用malloc_size输出查看大小;实际成员isa占用是8(64bit环境下),但是coreFoundtion框架内部规定小于16就分配16; (其实ios操作系统分配内存都是16的倍数,其实对象实际占不了那么大的内存) int 4个 bool 1个 class_getInstanceSize...

HPerry的博客 425

GraphRAG 与 HippoRAG 深度对比:在 RAGFlow 中如何选择知识图谱方案?

本文深入对比了GraphRAG与HippoRAG在RAGFlow中的知识图谱构建方案,分析了两者在技术架构、资源消耗和场景适配性上的核心差异。GraphRAG适合需要快速响应和资源有限的场景,而HippoRAG则更适用于精确关系推理的专业领域。文章还提供了RAGFlow的演进路线和选型决策框架,帮助架构师根据实际需求做出合理选择。

weixin_27889245的博客 247

【iOS】OC对象的本质底层原理

OC对象的本质-底层原理

cheng_lin0201的博客 867

企业微信消息推送API实战:5步搞定可信IP与域名配置(含Python代码示例)

本文详细解析了企业微信消息推送API实战中的关键配置步骤,特别是可信IP与可信域名的配置流程。通过5个清晰步骤,结合Python代码示例,指导开发者快速完成安全通信链路搭建,避免常见错误,确保消息推送服务稳定可靠。

qsc9012345的博客 996

BLDC方波控制 vs. FOC:技术选型指南与未来演进

本文深入对比BLDC电机方波控制与FOC技术的核心差异,分析两者在成本、性能和应用场景上的权衡。方波控制凭借低成本和易实现性,在电动工具和家电领域优势明显;而FOC则以平滑高效控制见长,适用于高端精密应用。文章为工程师提供了实用的技术选型指南,并展望了未来技术融合的发展趋势。

yhn4567890的博客 1172

OC对象 - Block 的本质

代码块,开发中常用来封装一段代码,在想要执行的时候再调用执行,也常用来做传值、事件传递等等,是不可或缺的一个特性。其实就是把我们 block 里面所写的代码封装成函数传进去。他实际上就是帮我们调用了刚刚初始化时传入的保存在。Desc则是block的描述信息,对应结构体。此时block里面的代码就被调用执行了。转成c++代码,来验证下它的底层结构。,可以看到此处代码传入的值是。我们初始化block后,通过。则表示 block 的大小。写一个最基础的block。构造方法接收两个参数。

sharp521的博客 574

如何使用PostgreSQL数据库进行数据仓库的ETL操作

本文旨在为数据工程师、数据库管理员和分析师提供使用PostgreSQL进行数据仓库ETL操作的全面指南。ETL流程的基本原理PostgreSQL在ETL中的独特优势实际ETL实现的技术细节性能优化和最佳实践常见问题的解决方案首先介绍ETL和PostgreSQL的基本概念然后深入探讨核心技术和实现方法接着提供实际案例和代码示例最后讨论优化技巧和未来趋势ETL:提取(Extract)、转换(Transform)、加载(Load)的缩写,描述数据从源系统移动到目标数据仓库的过程。

2502_91592937的博客 873

探寻OC对象的本质

iOS底层原理总结第一天 - 探寻OC对象的本质 对小码哥底层班视频学习的总结与记录。面试题部分,通过对面试题的分析探索问题的本质内容。 面试题:一个NSObject对象占用多少内存? 探寻OC对象的本质,我们平时编写的Objective-C代码,底层实现其实都是C\C++代码。 OC代码的转化过程 OC的对象结构都是通过基础C\C++的结构体实现的。 我们通过创建OC文件及对象,并将OC文件转化为C++文件来探寻OC对象的本质 OC如下代码 #import <Fo..

铭记_ 349

【PyTorch项目实战】图像分类与识别:手写数字识别(MNIST)、普适物体识别(CIFAR-10)

主要介绍了两个经典的实战项目:(1)基于 MNIST 数据集的手写数字识别(2)基于 CIFAR-10 数据集进行图像分类

📷 图像处理践行者 | 传统算法 · 深度学习 · 多模态 | 分享实战经验与技术洞见,探索从像素到智能的无限可能。 4401

RT-DETR训练自己的数据集(从代码下载到实例测试)

在Windows10上配置CUDA环境教程是百度提出的一种实时目标检测模型。RT-DETR采用了与DETR相同的编码器和解码器结构,但对其进行了大量的优化,在保持较高检测精度的同时,实现了实时目标检测,为目标检测领域提供了一种新的有效解决方案,具有广泛的应用前景,如自动驾驶、智能监控、机器人等领域。以上是RT-DETR官方的论文和代码,详细介绍了RT-DETR的构成和实现。在YOLOv10中也实现了RT-DETR的代码,所以本文使用YOLOv10的项目文件进行RT-DETR的训练和测试。YOLOv10。

Limiiiing的博客 4万+

OC底层学习-对象的本质

OC学习-对象的本质1. OC对象的本质1.1结构的内存对齐1.2 怎么把OC类通过终端转换成C++文件1.3 查看源码1.4面试题:一个NSObject的对象占多少内存?1.5实时查看内存数据1.6 常用的LLDB指令1.7 示例-验证-结论2 .Instance对象2.1 instance对象2.2 Class对象2.3 meta_class元类对象2.4 isa指针2.5 .面试题2.5.1 对象的isa指针指向哪里2.5.1 OC的类信息存放在哪里?2.5 答疑 1. OC对象的本质 OC代码经过

yong_19930826的博客 881

UNet改进(6):基于注意力机制的多尺度医学图像分割方法

本文提出了一种集成多尺度注意力机制的UNet改进模型UNetWithAttention,用于提升医学图像分割性能。该模型在标准UNet架构基础上,设计了并行3×3、5×5、7×7卷积核的多尺度注意力模块,通过特征拼接和Sigmoid激活生成注意力权重,实现了对不同尺寸病变的自适应关注。模型采用分离式设计,将特征提取与特征选择解耦,在编码器-解码器各阶段嵌入注意力模块。实验表明,该方法在视网膜血管分割和肺结节检测任务中优于标准UNet,Dice系数和IOU分别提升2.6%和4.1%,同时保持计算效率。

2501_91516851的博客 1324

OC对象本质

OC对象本质

Jackey_merlin的博客 162

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

OC对象原理探究(下)——OC对象的本质

一、对象的本质 1、对象的本质是结构体 我们都知道,Objective-C的底层都是通过C/C++来实现的,所以OC中的对象也会转化成C/C++中的某一个数据结构,然后再编译为汇编代码,最终转化为机器可以识别的二进制代码。 通过以下编译命令 xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp 将main.m转换为main.cpp文件 查看C++文件,我们可以看到类的结构 Class的定义,是一个结构体指针

罗永涛的技术博客 342

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

iOS底层原理总结 - 探寻OC对象的本质

原文链接 :iOS底层原理总结 - 探寻OC对象的本质 iOS底层原理总结 - 探寻OC对象的本质 对小码哥底层班视频学习的总结与记录。面试题部分,通过对面试题的分析探索问题的本质内容。 面试题:一个NSObject对象占用多少内存? 探寻OC对象的本质,我们平时编写的Objective-C代码,底层实现其实都是C\C++代码。 OC的对象结构都是通过基础C\C++的结构体实...

qq_34666585的博客 227

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

OC对象的本质(上)

这篇文章主要介绍的是OC对象转成C++语言以及OC对象的内存分配。 1.OC代码如何转成 C++代码,可以通过下面的命令: xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp 图片如下: OC代码转成C++代码之后,OC对象在C++里面对应的是一个结构体代码块,OC的成员变量对应的是结...

u011534162的专栏 244

OC底层原理——对象的本质

学习iOS这么长时间,都是把精力放在具体问题方法分析上,对iOS系统架构的层次很少关心,其实首先应该对整体架构有所了解,明白实际开发中是在哪个层次中开发,了解开发的应用所生存的环境。

草帽~小子^的博客 771

【iOS开发】iOS底层原理总结 - 探寻OC对象的本质

iOS底层原理总结 - 探寻OC对象的本质 方法调用图片

Hanrovey Blog 455

OC 对象创建的本质

OC 对象创建的本质就是用alloc进行创建,用init进行返回。但是为什么init没用任何用处还要写这个呢?这是为了代码的重写。就像我们可以在子类中重写父类的方法时一样的道理。 重点重点重点 oc的实例对象创建的时候最小16个字节。 size 被计算出来之前是需要对齐,加上一个值,苹果中这个值是0. 什么是字节对齐? arm64中字节对齐是8字节对齐。 3 --》8 9 --》16 其实字...

maniao1991的博客 275

OC对象的本质和OC方法的本质

OC对象的本质我们平时编写的Objective-C代码,底层实现其实都是C\C++代码,转换过程大致为OC--&gt;C/C++--&gt;汇编--&gt;机器语言Objective-C的对象、类主要是基于C\C++的结构体实现的实际上分配了16个字节的存储空间给NSObject对象真正有使用的空间是:一个指针变量所占用的大小(64bit,8个字节。32bit,4个字节)Objective-C中的...

howl_MK的博客 1004

[OC学习笔记]对象的本质探索

对象的本质 Objective-C 代码的底层都是通过 C/C++ 实现,所以 Objective-C 面向对象是基于 C/C++ 数据结构实现。

weixin_52192405的博客 531
上一篇: IOS 蓝牙技术之CoreBluetooth
下一篇: OC对象的分类
I微微一笑I
博客等级 码龄11年 0粉丝 86原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值