内存分区,编译链接,ARCMRC,消息传递消息转发,对象的底层

news2024/11/28 18:56:32

文章目录

  • 前言
  • 内存分区
    • 栈区
    • 堆区
    • 全局区
    • 文字常量区
    • 程序代码区
      • 运行之前
      • 运行之后
  • 编译,链接
    • 编译的过程
    • 链接
  • ARC,MRC
    • 在编译期干了什么
  • 对象的底层
  • 消息传递,消息转发
    • 消息转发
    • 消息传递
    • IMP指针
    • IMP与SEL的区别与联系


前言

对第一周学习内容做个概括


提示:以下是本篇文章正文内容,下面案例可供参考

内存分区

内存分区
内存一共分为五大区域,栈区,堆区,全局区,常量区,代码区

栈区

由编译器自动分配释放,存放函数的参数值

堆区

允许程序在运行时动态的申请某个大小的内存空间,一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
和数据结构里面的堆不一样

全局区

全局变量和静态变量的存储是放在一起的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后由系统释放。

文字常量区

常量字符串就放在这,它是只读的。程序结束后由系统释放。

程序代码区

存放程序的编译后的二进制代码,CPU执行的机器指令,并且是只读的。

程序在不同的阶段会在内存中占据不同的内存区域。

运行之前

运行之前,分为代码区,数据区,未初始化数据区。

运行之后

运行之后分为代码区,未初始化数据区,数据区,栈区,堆区

编译,链接

编译链接详细学习

编译的过程

  1. 预处理

这一步做了这几件事
宏替换:源代码中使用的宏定义会被替换为对应的#define内容
头文件引入:(#include,#import)
使用对应的.h文件内容替换这一行的内容,所以尽量减少头文件的#import,使用@class代替,把#import放到.m文件中
处理条件编译指令:(#if,#else,#endif)

  1. 词法分析

把原文件中的代码转化为特殊的标记流,源码被分为一个一个的单词,在行尾Loc中都标记出了源码所在的对应的原文件和具体行数,方便在报错的时候定位问题

  1. 语法分析

把此词法分析生成的标记流,解析成为一个抽象语法树,这里面的每一节点也都标记了其在源码中的位置

  1. 静态分析

把源码转化为抽象语法树后,编译器就可以对这个树进行处理。静态分析会对代码进行错误检测,如出现方法被调用但是未定义,定义但是未使用的变量等。
类型检查:clang做检查,检查程序是否发送正确的消息给正确的对象,是否在正确的值上调用了正常函数
其他分析:ObjCUnusedIVarsChecker.cpp检查是否有生成了但是从未使用的变量。ObjCSelfInitChecker.cpp是检查在 你的初始化方法中中调用 self 之前,是否已经调用[self initWith…]或[super init]了

  1. 生成中间代码和优化

LLVM有三种表示形式,他们本质上是等价的
text:文本格式
memory:内存格式
bitcode:二进制格式

  1. 汇编

汇编器将上一步生成的刻度的汇编代码转化为机器代码,最终产物是以.o结尾的目标文件。

链接

在编译的最后一步汇编结束后,就到了链接这一步

将上一步产生的目标文件和引用的静态库链接起来,最终生成可执行文件,链接解决了目标文件和库之间的链接

ARC,MRC

ARC的工作原理

在编译期干了什么

ARC会把能够相互抵消的retain、release、autorelease操作约简
ARC会分析对象的生存期需求,并在编译时自动插入适当的内存管理方法调用的代码
编译器还会为你生成合适的dealloc方法
将内存管理交由编译器和运行期组件来做,可以使代码得到多种优化

对象的底层

对象的底层详细学习

OC对象的本质就是结构体
struct NSObject_IMPL结构体事实上是一个Class类型的isa指针
objc_class是继承objc_object的
每个类的底层都会有一个Class类的isa指针。
Class底层是struct objc_class *类型,NSObject底层是struct objc_object结构体,id底层是struct objc_object *类型

struct objc_object {
    Class _Nonnull isa __attribute__((deprecated));
};

id底层实现是struct objc_object 类型,怪不得声明id类型变量时 后面不用再加""了,因为它定义的时候就定义为了一个Class的指针

SEL是struct objc_selector 类型
IMP是void (
)(void )函数指针类型

struct objc_class : objc_object {
    //...省略无关代码
    // Class ISA;  //ISA(从objc_object继承过来的)
    Class superclass;  //指向其父类
    cache_t cache;  //缓存
    class_data_bits_t bits;  //类的数据
    
	class_rw_t *data() const {
        return bits.data();
    }
    void setData(class_rw_t *newData) {
        bits.setData(newData);
    }
    //...省略无关代码
}  

所有对象都是以objc_object为模板继承过来的。
类是一个结构体,里面存放了isa、superClass、cache、bits等

isa指针保存着指向类对象的内存地址,类对象全局只有一个,因此每个类创建出来的对象都会默认有一个isa属性,保存类对象的地址,也就是class,通过class就可以查询到这个对象的属性和方法,协议

源码主要是初始化isa,两种方式:

通过cls初始化:
非nonpointer,存储着Class、Meta-Class对象的内存地址信息。
通过bits初始化:
nonpointer,进行一系列的初始化操作。

消息传递,消息转发

消息传递和消息转发详细学习

消息转发

iOS的消息转发是指当一个对象收到一个无法响应的消息时,其会通过多个方法转发该消息,直到能够响应为止
当消息接收者无法响应某个方法时,Objective-C消息传递机制会按照以下顺序进行转发

  1. 动态方法解析
  2. 备援接收者
  3. 完整消息转发

如果没有找到消息,该怎么处理呢?就需要消息转发。
消息转发机制大致可分为三个步骤:

  1. 动态方法解析
  2. 备援接受者
  3. 完整消息转发

请添加图片描述

消息传递

在 iOS 中,消息传递是指通过向对象发送消息并让其执行对应的方法,从而实现组件间的通信和协作。

在 Objective-C 中,消息传递是通过向对象发送消息来实现的。当一个对象收到消息时,Objective-C 运行时会根据消息所带的函数名(即 Selector),查找该对象所属的类中是否有对应的方法实现。如果找到,则运行时会执行该方法实现;如果没找到,则会先尝试进行动态方法解析,再尝试进行消息转发

在 Objective-C 中,消息直到运行时才绑定到方法实现上。编译器会将消息表达式转化为一个消息函数的调用。

IMP指针

IMP本质就是一个函数指针,这个被指向的函数包含一个接收消息的对象id,调用方法的SEL,以及一些方法参数,并返回一个id。因此我们可以通过SEL获得它所对应的IMP,在取得了函数指针之后,也就意味着我们取得了需要执行方法的代码入口,这样我们就可以像普通的C语言函数调用一样使用这个函数指针

IMP与SEL的区别与联系

SEL:类方法的指针,相当于一种编号,区别与IMP
IMP:函数指针,保存了方法的地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/769266.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

no module named paddle pip install paddlepaddle报错

!python -m pip install paddlepaddle2.4.2 -i https://pypi.tuna.tsinghua.edu.cn/simple

Python实战项目——餐厅订单数据分析(一)

项目背景 餐厅经营的好坏需要用数据来说明,如果一个餐厅生意惨淡,那么应该先收集最近的数据,然后进行数据分析,再对应相应出现的问题进行解决和做出对应的商业调整。今天开始我们分析一来家餐厅的数据。 认识数据并预处理 拿到…

GUI-Menu菜单实例

运行代码: //GUI-Menu菜单实例 #include"std_lib_facilities.h" #include"GUI/Simple_window.h" #include"GUI/GUI.h" #include"GUI/Graph.h" #include"GUI/Point.h"struct Lines_window :Window {Lines_window…

Appium+python自动化(十二)- Android UIAutomator终极定位凶器(超详解)

简介 乍眼一看,小伙伴们觉得这部分其实在异性兄弟那里就做过介绍和分享了,其实不然,上次介绍和分享的大哥是uiautomatorviewer,是一款定位工具。今天介绍的是一个java库,提供执行自动化测试的各种API。 Android团队在4…

小程序控制台警告:DevTools failed to load SourceMap(控制台报错DevTools 无法加载来源映射)

在调试项目的时候,控制台报错:**DevTools failed to load SourceMap: Could not load content for http://xxx.js. 这段报错的意思是dev工具未能成功加载source map(文件映射)。这里的报错实际上和项目本身的代码没有任何关系,而是…

基于 Fedora 38 的预期版本 Nobara 38 发布

导读基于 Fedora 38 的预期版本 Nobara 38 终于发布了,它带来了一系列用户友好的修复和功能增强。Nobara 是 Fedora Linux 的修改版本,旨在解决用户面临的常见问题,并提供开箱即用的顺滑的游戏、流媒体和内容创建体验。凭借一系列附加软件包和…

HTTP 缓存机制 强制缓存/协商缓存

Web 缓存大致可以分为:数据库缓存、服务器端缓存(代理服务器缓存、CDN 缓存)、浏览器缓存。 浏览器缓存也包含很多内容: HTTP 缓存、indexDB、cookie、localstorage 等等。这里我们只讨论 HTTP 缓存相关内容。 在具体了解 HTTP …

美国电动汽车公司Lucid在中国市场的投资机会

来源:猛兽财经 作者:猛兽财经 总结: (1)Lucid计划进入快速增长的中国电动汽车市场,未来可能会加速交付和收入增长。 (2)中国人口众多,电动汽车采用率高,政府…

深度学习开发环境

Ubuntu搭建深度学习开发环境(Pytorch Tensorflow GPU版本) 显卡驱动系列 深度学习主要涉及到显卡的使用(如开发时使用GPU版本库,就需要提前安装好显卡驱动方可使用),所以这里主要说明显卡驱动的安装。 显卡驱动(Driver) | 官网:显卡驱动下载CUDA(NVID…

汤姆猫+AI求IP“翻红”?股东年内忙减持

作为初代手机宠物陪伴游戏,“会说话的汤姆猫”曾在全球积累了大量粉丝,汤姆猫IP也成为一代经典。2017年,A股上市公司金科文化将诞生自海外“汤姆猫”收入麾下。你或许不知道,汤姆猫已成为中国A股市场的一只股票代码。 在金科文化…

曲师大2023大一新生排位赛-B.Sort题解

题目描述 插入排序是一种非常常见且简单的排序算法。王同学是一名大一的新生,今天许师哥刚刚在上课的时候讲了插入排序算法。 假设比较两个元素的时间为 ,则插入排序可以以 的时间复杂度完成长度为 n� 的数组的排序。不妨假设这 n 个数字分…

如何将大批量将行驶证合并转为excel?

我们知道,金鸣识别小程序和网页在线版都支持将行驶证转为excel,但这二种方案只适合小量、零星的转换(小程序只能一次提交4张图片,网页在线版只能一次提交5张),要想大批量识别,就要下载安装金鸣识…

栈与队列 理论基础

我们都知道栈和队列是STL(C标准库)里面的两个数据结构。 栈是前进后出,队列是先进先出 C标准库是有多个版本的,要知道我们使用的STL是哪个版本,才能知道对应的栈和队列的实现原理。 那么来介绍一下,三个最…

springboot项目自定义注解+Aop实现收集日志

一 工程结构 二 配置 2.1 配置pom <!--spring boot的启动类 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.…

Sentinel的线程隔离和熔断降级

上一节整理了Sentinel的限流&#xff0c;限流可以降低微服务的负载&#xff0c;避免因为高并发而故障&#xff0c;进而传递给其他相关服务而引发服务雪崩。以上仅为避免服务故障&#xff0c;而当某个服务真正故障时&#xff0c;如何处理才能防止服务雪崩&#xff1f; ⇒ Sentin…

二十一、vm 适配

目录&#xff1a; 1. 基础准备 2. 详解 一、基础准备 目的&#xff1a;前面我们通过0.1333vm x 对应的设计图像素&#xff0c;找到vm值&#xff0c;这个方法不准确&#xff0c;且操作复杂&#xff0c;有没有什么优化方法呢&#xff1f; 解决&#xff1a;vw的适配&#xff08;在…

Bard:一个可以描述图像的人工智能

Bard 是一个大型语言模型&#xff0c;可以对各种提示和问题进行交流和生成类似人类的文本。它接受了大量的文字和代码训练&#xff0c;可以生成文本、翻译语言、编写不同类型的创意内容&#xff0c;并以信息丰富的方式回答你的问题。 Bard 还可以识别图像。它可以识别图像中的…

python编程语言之进阶语法

迭代器 可迭代对象 讲迭代器之前&#xff0c;我们先了解一个概念&#xff1a;可迭代对象(Iterable)。 那么什么是可迭代&#xff1f;什么是对象&#xff1f; 迭代(Iteration)&#xff0c;是指通过遍历获取某容器内所有元素&#xff0c;特指遍历获取这个动作。 可迭代 (iter…

EasyCVR录像阈值配置未生效,是什么原因?

有用户反馈&#xff0c;在平台中设置了录像阈值不生效&#xff0c;导致磁盘爆满。针对该反馈&#xff0c;我们立即进行了排查。 EasyCVR基于云边端一体化架构&#xff0c;可支持多协议、多类型设备接入&#xff0c;在视频能力上&#xff0c;平台可实现视频直播、录像、回放、检…

用C语言对学生成绩进行排序(归并排序与基数排序)

一.前言 我们内部排序已经学了插入排序&#xff08;直接插入排序、折半插入排序、希尔排序&#xff09;&#xff0c;交换排序&#xff08;冒泡排序、快速排序&#xff09;&#xff0c;选择排序&#xff08;简单选择排序、堆排序&#xff09;&#xff0c;这些都属于内部排序&…