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

STM32F030C8烧录实战:用J-Link Commander实现一键批量烧写(附完整脚本) 本文详细介绍了如何使用J-Link Commander工具链实现STM32F030C8的一键批量烧录,包括环境配置、批处理脚本设计、命令脚本解析以及生产环境实战技巧。通过自动化烧录流程,显著提升效率并降低人为错误,特别适合量产和频繁迭代的开发场景。 阅读详情

相关推荐

新手避坑:RT-Thread-Studio外设驱动配置最容易忽略的3个地方(附WDT实例)

本文针对RT-Thread-Studio新手在配置外设驱动时常见的编译报错问题,以看门狗(WDT)为例,详细解析了最易忽略的三个关键配置环节:RT-Thread-Studio的图形化Setting开关、Kconfig中的依赖关系以及SConscript的编译规则。掌握这三层配置模型,能有效避免头文件包含正确却依然编译失败的问题,确保驱动代码被正确加入构建。

gray5的博客 506

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

告别QWebEngineView!用QtLocation+SQLite打造离线地图应用(附完整源码)

本文详细介绍了如何利用QtLocation模块与SQLite数据库构建高性能离线地图引擎,解决传统QWebEngineView方案在网络依赖、内存占用和定制化方面的不足。通过多级缓存机制、异步写入优化和纹理压缩技术,实现工业级应用的稳定运行和高效渲染,特别适合车载导航和野外勘探等场景。

weixin_30431445的博客 363

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

OC对象的本质-底层原理

cheng_lin0201的博客 867

Cadence SIP Layout 简单教程-第一章

以摄像头模组软硬结合板为例,描述layout的整个完整过程,从而掌握基本技能。 第一章 准备工作 第一节 原理图不用说layout前需要绘制原理图,原理图不在本文讨论范围内,所以列为准备工作。 需要特别说明的是,绘制原理的最终目的是导出网络表,网络表中的重要参数footprint是让layout软件选择正确封装的关键,所以这里讲解一下原理图设置footprint的位置。在原理图中双击零件,...

whp1920的博客 1万+

Coze平台智能体开发实战:打造测试工程师的AI助手

智能体是具备特定身份和能力的AI实体,由大语言模型(LLM)驱动,并通过插件、知识库和工作流扩展其能力。明确的角色定位:可以设定特定身份和专业领域扩展能力:通过插件连接外部工具和服务记忆能力:通过知识库存储和检索专属信息流程化处理:通过工作流执行复杂多步任务通过Coze平台创建测试工程师智能体,可以显著提升测试效率和质量。明确的角色定位:聚焦测试工程师的实际需求丰富的知识库:提供准确的领域知识支持合适的工具集成:通过插件连接现有工具链持续迭代优化:根据反馈不断改进智能体行为自动化测试生成。

hogwarts_beibei的博客 1005

OC对象 - Block 的本质

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

sharp521的博客 574

SAP 系统中的数字签名解决方案及应用案例分析

在当前企业信息化及数字化转型的大背景下,数据安全与身份认证显得尤为重要。数字签名技术作为保障数据真实性和完整性的重要手段,在 SAP 系统中得到了广泛应用。本文将详细探讨 SAP 系统中部分应用场景如何利用数字签名技术满足业务需求,涵盖 SAP Single Sign-On、质量管理、过程工业生产计划以及 SAP ArchiveLink 内容服务器等方面,力求通过深入解读,帮助读者更好地理解和应用这一关键技术。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 527

探寻OC对象的本质

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

铭记_ 349

3. 动手运行第一个 SAP Fiori Elements 应用(ListReport 类型)

这个代理服务器能够自动监听我们 Fiori Elements 应用里向 ES5 Demo 系统发送的 OData 请求,拦截这个请求,并通过 Node.js 代码向 ES5 服务器转发,拿到响应数据后再交还给 Fiori Elements 应用。后者对自己发出的请求被代理这件事情一无所知。本文的任务是,大家按照我的介绍,在本地成功运行笔者准备的这个 Fiori Elements 应用。的错误消息, 说明大家安装的 Node.js 版本没有达到本地运行 Fiori Elements 的最低要求。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1671

【YOLO26实战全攻略】19——智慧交通(一):高速抛洒物与事故检测全流程落地

在智慧交通领域,高速公路抛洒物、交通事故等突发状况常导致二次事故与大规模拥堵,传统人工监控存在响应滞后、覆盖有限等痛点。本文基于Ultralytics YOLO26算法,结合ByteTrack多目标跟踪技术,构建从数据准备、模型训练到边缘部署的全栈式智慧交通检测系统。核心内容包括:多车型专属数据集构建、抛洒物检测模型优化、ByteTrack轨迹跟踪集成、异常事件(违停/逆行/碰撞)识别逻辑实现,以及NVIDIA Jetson边缘设备部署方案。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1491

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

如何使用 Claude Code 搜索 SAP note

当然,Claude Code 自己仍然要有一种合法可用的模型访问方式,例如 Claude 订阅、Anthropic API 或公司配置的模型提供方式,这和 Browser Extension 是两个问题。因为 Claude Code 已经是完整的 MCP Host,而 Microsoft Playwright MCP 又已经明确支持现有 Chrome Session,两者拼起来在技术架构上完全成立。Microsoft Playwright MCP 默认可以创建持久化浏览器 Profile。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 65

OC对象本质

OC对象本质

Jackey_merlin的博客 162

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

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

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

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

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

qq_34666585的博客 227

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

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、付费专栏及课程。

余额充值