当前位置: 首页 > news >正文

Swift闭包(Closure)深入解析与底层原理

前言

在Swift开发中,闭包是一个非常重要且强大的特性。本文将深入探讨Swift闭包的底层实现原理,帮助开发者更好地理解和使用这一特性。

1. 什么是闭包

闭包是自包含的函数代码块,可以在代码中被传递和使用。它不仅可以像函数一样执行代码,还能捕获和存储定义时上下文中的常量和变量。Swift中的闭包类似于其他语言中的lambda或匿名函数。

// 基础闭包语法
let simpleClosure = { (x: Int) -> Int inreturn x * 2
}

 

2.  闭包的底层实现

从内存模型的角度来看,闭包是一个特殊的函数类型,其底层实现包含了执行代码和上下文环境。Swift中闭包的内存布局由三个核心组件构成:

2.1 闭包的内存结构

  • 代码块:包含可执行逻辑的指令集

  • 捕获上下文:存储环境变量的容器

  • 元数据信息:包含参数类型和返回类型的元数据

//伪代码
struct SwiftClosureLayout {var invokeFunction: FunctionPointervar context: HeapObjectvar metadata: ClosureMetadata
}

2.2 详细内存组成

2.2.1 函数指针(Function Pointer)

//伪代码
struct FunctionPointer {var codeAddress: UnsafeRawPointer  // 指向实际代码段的指针var flags: UInt32                  // 函数标志位var parameterCount: UInt32         // 参数计数
}
  • 存储闭包的实际执行代码地址
  • 包含函数调用约定信息
  • 记录参数和返回值类型信息

2.2.2 上下文对象(Context)

//伪代码
class HeapObject {var metadata: Metadata            // 类型元数据var refCount: AtomicInt          // 引用计数var capturedVariables: [Any]     // 捕获的变量
}
  • 采用引用计数管理内存
  • 存储所有捕获的变量
  • 维护变量的生命周期

2.2.3 元数据信息(Metadata)

//伪代码
struct ClosureMetadata {var kind: Int                    // 闭包类型var captureDescriptor: UInt32    // 捕获描述符var genericEnvironment: UInt32   // 泛型环境信息
}
  • 闭包的类型信息
  • 捕获变量的布局描述
  • 泛型参数信息(如果有)

3. 捕获机制详解

闭包捕获(Closure Capture)是Swift中一个重要的概念,它允许闭包捕获并存储在其定义环境中的变量和常量的引用。

3.1 值捕获 (Value Capture)

  • 在闭包创建时会对值进行拷贝。捕获的是变量的副本,而不是变量本身。
  • 闭包内的值不会随外部变量改变而改变。
  • 适用于值类型(如 Int、String、Struct 等)。
var number = 42
let closure = { [number] in print(number)
}
number = 100
closure() // 打印: 42

3.2 引用类型捕获(Reference Capture)

  • 在闭包创建时捕获变量的内存地址而非内容副本,闭包与外部变量共享同一内存空间。
  • 闭包内的值会实时跟随外部变量的变化而变化。
  • 主要用于引用类型(如Class)。

3.2.1 强引用捕获(Strong Capture)

默认的捕获方式,会增加引用计数并持有对象的强引用,直到闭包被释放,适用于确保对象在闭包执行期间不会被释放的场景。

let strongClosure = {self.doSomething()
}

3.2.2 弱引用捕获(Weak Capture)

不会增加引用计数,对象可能被释放变为nil,使用可选绑定访问,主要用于防止循环引用,适用于delegate模式和异步回调场景。

let weakClosure = { [weak self] inself?.doSomething()
}

3.2.3 无主引用捕获(Unowned Capture)

不增加引用计数且假定对象一定存在,如果对象被释放会导致崩溃,适用于确保闭包生命周期短于捕获对象的场景,如视图控制器中的短期动画闭包。

let unownedClosure = { [unowned self] inself.doSomething()
}

3.2.4 引用类型捕获对比

捕获方式引用计数安全性使用场景
strong+1同步操作
weak不变异步回调
unowned不变生命周期明确

3.3 多变量捕获机制

3.3.1 基本概念

当一个闭包同时捕获多个变量时,Swift会在底层创建一个特殊的上下文容器来管理这些变量。这个容器被称为"捕获上下文"(Capture Context)。

3.3.2 捕获上下文的构成

捕获上下文主要包含三个部分:

// 编译器生成的大致结构,伪代码
struct ClosureContext {// 值类型通过拷贝存储var valueTypeVars: ValueContainer// 引用类型通过指针存储var referenceTypeVars: ReferenceContainer// 捕获列表信息var captureDescriptor: CaptureDescriptor
}
  1. 值类型存储区:存储Int、String等值类型变量
  2. 引用类型存储区:存储类实例等引用类型变量
  3. 捕获列表信息:存储类型信息和引用计数等管理数据

举个简单的例子:

func example() {var count = 0          // 值类型let cache = Cache()    // 引用类型let closure = { [weak cache] incount += 1cache?.update()}
}

在这个例子中,Swift会为count在值类型区创建独立存储空间,为cache在引用类型区创建弱引用指针。自动管理这两种不同类型的内存布局。

3.4  inout与值捕获的突破:修改外部值类型

在Swift中,当我们在闭包中捕获值类型时,通常只能获得该值的副本,这意味着我们无法在闭包中修改原始值。然而,通过inout参数,我们可以突破这个限制。

var number = 42func modifyValue(_ value: inout Int) {value += 1
}modifyValue(&number)

当我们使用inout时,Swift实际做了什么?

  • 第一步:获取变量的内存地址,创建内存访问器,设置安全检查机制。

//伪代码
struct AddressAccessor {let address: UnsafeMutablePointer<Int>let originalValue: Int// 开始访问时func beginAccess() {// 标记这块内存正在被访问markExclusiveAccess(address)}// 结束访问时func endAccess() {// 解除内存访问标记unmarkExclusiveAccess(address)}
}// Swift运行时会这样管理内存访问
class MemoryAccessManager {// 记录当前正在访问的内存地址static var activeAccesses: Set<UnsafeRawPointer> = []static func checkAccess(_ address: UnsafeRawPointer) {if activeAccesses.contains(address) {// 如果地址已经被访问,抛出错误fatalError("内存访问冲突")}activeAccesses.insert(address)}
}
  • 第二步:标记内存独占访问,在原地址上修改值,确保修改的原子性。

  • 第三步:解除内存独占访问,确保修改已同步,清理访问记录。

// 伪代码
func performModification(_ accessor: AddressAccessor, _ operation: (inout Int) -> Void) {// 1. 开始独占访问accessor.beginAccess()// 2. 执行修改var localValue = accessor.address.pointee  // 读取值operation(&localValue)  // 修改值accessor.address.pointee = localValue  // 写回原地址// 3. 结束独占访问accessor.endAccess()
}

4. 逃逸闭包与非逃逸闭包的深度解析

Swift中的闭包分为非逃逸闭包和逃逸闭包,它们在内存管理和使用场景上有着本质的区别。

4.1 基本概念对比

非逃逸闭包在函数返回前执行,是默认形式,无需特殊标记,生命周期可预测,便于编译器优化。

逃逸闭包可在函数返回后执行,需要使用 @escaping 标记,提供更灵活的执行时机,常用于异步操作和回调函数。

// 非逃逸闭包示例
func execute(closure: () -> Void) {closure()  // 直接在函数内执行
}// 逃逸闭包示例
class NetworkManager {var handler: (() -> Void)?  // 存储属性中的闭包自动成为逃逸闭包func fetch(completion: @escaping () -> Void) {DispatchQueue.main.async {completion()  // 异步执行}}
}

4.2 内存分配机制

非逃逸闭包分配在栈上,生命周期与函数栈帧绑定,函数返回时自动释放,无需额外内存管理。

逃逸闭包分配在堆上,创建闭包上下文对象,包含函数指针、捕获变量和引用计数等信息,支持函数返回后的持续存在。

4.3 性能影响

非逃逸闭包性能更优,因为编译器可进行内联展开和栈上分配优化,无需引用计数管理。

逃逸闭包会产生堆内存分配、引用计数管理等开销,还需考虑循环引用问题。

4.4 使用场景

非逃逸闭包适用于即时执行的同步操作,如数组高阶函数、UI配置等。

逃逸闭包主要用于异步操作、回调函数和观察者模式等需要延迟执行的场景。

总结

Swift闭包的核心要点

  1. 闭包本质:闭包是一个包含执行代码和上下文环境的特殊函数类型。
  2. 内存结构:闭包由函数指针、上下文对象和元数据信息三部分组成。
  3. 捕获机制:支持值捕获和引用捕获,可通过strong、weak、unowned控制引用方式。
  4. 内存管理:非逃逸闭包在栈上分配,逃逸闭包在堆上分配。
  5. 性能特点:非逃逸闭包性能更优,因为可以进行编译器优化。

实践建议

  1. 优先使用非逃逸闭包,除非确实需要延迟执行。
  2. 注意防止循环引用,合理使用weak和unowned。
  3. 异步操作和回调场景使用@escaping标记。
  4. 根据实际场景选择合适的变量捕获方式。
  5. 理解inout参数的使用时机,合理修改外部值类型。

应用场景

  1. 同步操作:使用非逃逸闭包。
  2. 异步回调:使用逃逸闭包。
  3. 委托模式:使用weak捕获。
  4. 短期动画:使用unowned捕获。
  5. 数据处理:使用值捕获。

如果觉得本文对你有帮助,欢迎点赞、收藏和分享!

相关文章:

Swift闭包(Closure)深入解析与底层原理

前言 在Swift开发中&#xff0c;闭包是一个非常重要且强大的特性。本文将深入探讨Swift闭包的底层实现原理&#xff0c;帮助开发者更好地理解和使用这一特性。 1. 什么是闭包 闭包是自包含的函数代码块&#xff0c;可以在代码中被传递和使用。它不仅可以像函数一样执行代码&…...

【DE-III】基于细节增强的模态内和模态间交互的视听情感识别

abstract 在视听情感识别(AVER)中,捕捉视频和音频模态之间复杂的时间关系是至关重要的。然而,现有的方法缺乏对局部细节的关注,如视频帧之间的面部状态变化,这会降低特征的可区分性,从而降低识别准确率。 为此,本文提出了一种用于AVER的细节增强的模态内和模态间交互…...

c++11 :智能指针

目录 一 为什么需要智能指针&#xff1f; 二 智能指针的使用及原理 1. RAII 2. auto_ptr 3. unique_ptr 4. shared_ptr 5. weak_ptr 三 内存泄漏 1.什么是内存泄漏&#xff0c;内存泄漏的危害 2. 如何避免内存泄漏&#xff1f; 一 为什么需要智能指针&#xff1f; …...

Linux解压tar.gz包的正确姿势(附赠防抓狂指南)

一、为什么你的解压命令总报错&#xff1f; 每次看到.tar.gz后缀是不是心里一紧&#xff1f;&#xff08;别装了&#xff01;我都看到你偷偷打开浏览器查命令的样子了&#xff09;这个在Linux界横行霸道的压缩格式&#xff0c;其实用对了方法比Windows的zip还简单。今天咱们不…...

MCP协议:让AI从“话痨”变“实干家”的神奇魔法

一、MCP 协议&#xff1a;AI 界的 “万能插头” 是啥来头&#xff1f; 1.1 从 “动口不动手” 到 “全能打工人” 你以为 AI 只会陪你聊天、写文案&#xff1f;那你可小瞧它啦&#xff01;MCP 协议&#xff08;Model Context Protocol&#xff09;&#xff0c;堪称 AI 的 “瑞…...

如何在SpringBoot中通过@Value注入Map和List并使用YAML配置?

在SpringBoot开发中&#xff0c;我们经常需要从配置文件中读取各种参数。对于简单的字符串或数值&#xff0c;直接使用Value注解就可以了。但当我们需要注入更复杂的数据结构&#xff0c;比如Map或者List时&#xff0c;该怎么操作呢&#xff1f;特别是使用YAML这种更人性化的配…...

记一次调用大华抓拍SDK并发优化

目录 一、问题分析 二、解决思路 三、贴代码 四、总结 一、问题分析 按惯例上问题&#xff1a; 设备告警采用高电平持续模式&#xff1a;一次开&#xff0c;不主动关就一直处于告警状态。 并发时多个请求下发 setDVRAlarmOutConfig&#xff0c;导致状态混乱。 “开 -&g…...

打破认知!没论文没竞赛,我的暑期实习上岸秘籍:简历要敢 “吹”,面试靠巧 “聊”

前言 以下教程仅针对本人的大大小小几十场暑期实习面试的经验总结&#xff0c;个人背景&#xff08;双9&#xff0c;无论文、无竞赛、无大厂实习、无奖。&#xff09;。简历几易其稿&#xff0c;相对于原来的初版&#xff0c;可谓是脱胎换骨&#xff0c;洗经易髓。 二月中旬开…...

为何 RAG 向量存储应优先考虑 PostgreSQL + pgvector 而非 MySQL?

构建检索增强生成&#xff08;RAG&#xff09;系统已成为释放大型语言模型&#xff08;LLM&#xff09;潜力的关键范式。通过将 LLM 的推理能力与外部知识库的实时、特定信息相结合&#xff0c;RAG 能够生成更准确、更相关、更值得信赖的回答。而这个“外部知识库”的核心&…...

LangChain LCEL表达式语言简介

LangChain表达式语言&#xff08;LCEL&#xff09;是专为构建AI应用链设计的声明式编程框架&#xff0c;通过管道符|实现组件无缝衔接&#xff0c;支持流式处理、异步调用等生产级特性。其核心优势在于零代码改动实现原型到生产的过渡&#xff0c;同时保持代码简洁性和可维护性…...

智能座舱背后的秘密:智能座舱测试如何“具身智能”

在上期文章《智能座舱背后的秘密&#xff1a;AI赋能测试如何改写驾乘体验》中&#xff0c;我们聊到了“智能座舱”已成为车企争夺用户心智的核心战场、智能座舱功能体验进化、AI赋能座舱测试将突破“场景覆盖、情感量化、角色/场景衍生”技术实现方面的三大困局&#xff0c;并在…...

鸿蒙-试一下属性字符串:除了Span之外,如何在同一个Text组件中展示不同样式的文字

文章目录 前言简介有哪些类型拉出来溜溜Text SpanStyledString其他CustomSpan先看一下构造函数onMeasure(measureInfo: CustomSpanMeasureInfo): CustomSpanMetricsonDraw(context: DrawContext, drawInfo: CustomSpanDrawInfo) 遗留问题 前言 在开发中&#xff0c;经常会遇到…...

今日最新漂亮的早上好图片祝福,最真的牵挂,永远的祝福

1、清晨的一个问候给你一个新的心情、一个祝福带给你新的起点、一个关心带给你一个新的愿望。祝福你心中常有快乐涌现&#xff01;早安&#xff01; 2、人过花甲万事休&#xff0c;唯有健康不可丢&#xff0c;荣华富贵皆浮云&#xff0c;逍遥自在渡岁月&#xff01;时光匆匆&am…...

MySQL 库的操作 -- 增删改查,备份和恢复,系统编码

文章目录 库的操作增删改查数据库的查看和创建查看当前位于哪个数据库中数据库的删除总结显示数据库的创建语句修改数据库 认识系统编码数据库的编码问题查看系统默认的字符集和效验规则校验规则对数据库的影响 数据库的备份和恢复备份还原备份的是一张表 查看数据库的连接情况…...

【c++11】c++11新特性(下)(可变参数模板、default和delete、容器新设定、包装器)

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C 目录 前言 五、可变参数模板 1. 概念及简单定义 2. 包扩展 六、 default和delete 七、容器新设定 1. 新容器 2. 新接口 emplace系列接口 八、函数包…...

fps项目总结:生成武器子弹

文章目录 spawn actor&#xff1a;生成武器固定生成&#xff1a;因为武器的碰撞设为noCollision attach actor to component&#xff1a;将武器附加到骨骼上&#xff0c;成为mesh的子组件对齐到目标&#xff1a;对齐到插槽 子弹阻挡的前提是根组件为碰撞体子弹对碰撞体全是阻挡…...

大模型备案对模型训练语料的要求

昨天接到一位客户的咨询&#xff0c;说他们的模型还在开发阶段&#xff0c;想提前了解一下大模型备案政策中对于模型训练语料有什么具体要求&#xff0c;提前规避一下。客户确实有前瞻性&#xff0c;考虑得比较充分。训练语料在研发阶段至关重要&#xff0c;直接影响模型的性能…...

Ethan独立开发产品日报 | 2025-04-24

1. Peek AI个人财务教练&#xff0c;帮助你做出决策。 Peek的人工智能助手提供主动的跟踪服务——它会分析你的消费习惯&#xff0c;并以细腻而积极的方式帮助你调整这些习惯。没有评判&#xff0c;也没有负担。就像是为你的财务量身定制的Spotify Wrapped&#xff0c;完美贴…...

egg环境搭建

前言 egg.js 是由阿里开源的面向企业级开发的 Node.js 服务端框架&#xff0c;它的底层是由 Koa2 搭建。 Github&#xff1a;https://github.com/eggjs/egg&#xff0c;目前 14.8K Star&#xff0c;egg 很适合做中台。 安装 首先&#xff0c;你要 确保 Node 已经配置环境变量…...

Linux的基础指令

目录 1、Shell及运行原理 2、热键 3、Linux的基础知识 4、Linux的基础指令 4.1 man 4.2 clear&&history&&whoami 4.3 pwd 4.4 ls 4.5 cd 4.6 mkdir&&touch 1. mkdir 2. touch 4.7 rmdir&&rm 1. rmdir 2. rm 4.8 cp&&mv…...

第一部分:git基本操作

目录 1、git初识 1.1、存在的问题 1.2、版本控制器 1.3、git安装 1.3.1、CentOS平台 1.3.2、ubuntu平台 2、git基本操作 2.1、创建仓库 2.2、配置git 3、工作区、暂存区、版本库 4、基本操作 4.1、场景一 4.2、场景二 4.3、修改文件 5、版本回退 6、撤销修改 …...

Kafka和其他组件的整合

Kafka和其他组件的整合 1.Kafka和Flume的整合 需求1&#xff1a;利用flume监控某目录中新生成的文件&#xff0c;将监控到的变更数据发送给kafka&#xff0c;kafka将收到的数据打印到控制台&#xff1a; 在flume/conf下添加.conf文件&#xff0c; vi flume-kafka.conf # 定…...

学习AI必知的20大概念

&#x1f3af;AI开发者必知的20大概念 ​&#x1f916; 机器学习&#xff1a;基础算法和模型训练。 &#x1f9e0; 深度学习&#xff1a;复杂表示学习。 &#x1f310; 神经网络&#xff1a;非线性关系建模。 &#x1f5e3;️ NLP&#xff1a;文本处理和理解。 &#x1f441;️…...

VRRP与防火墙双机热备实验

目录 实验一&#xff1a;VRRP负载均衡与故障切换 实验拓扑​编辑一、实验配置步骤 1. 基础网络配置 2. VRRP双组配置 二、关键验证命令 1. 查看VRRP状态 2. 路由表验证 三、流量分析 正常负载均衡场景&#xff1a; 故障切换验证&#xff1a; 实验二&#xff1a;防火…...

【金仓数据库征文】——选择金仓,选择胜利

目录 第一部分&#xff1a;金仓数据库——开创数据库技术的新时代 1.1 金仓数据库的技术底蕴 1.2 高可用架构与灾备能力 1.3 分布式架构与弹性扩展能力 第二部分&#xff1a;金仓数据库助力行业数字化转型 2.1 电信行业&#xff1a;核心系统国产化替代 2.2 医疗行业&…...

微软官网Win10镜像下载快速获取ISO文件

如何从微软官网轻松下载win10镜像&#xff1f;win10镜像的下载方式主要包括两种&#xff1a; 目录 一&#xff1a;借助官方工具 二&#xff1a;直接微软官网通过浏览器进行下载。 三&#xff1a;实现方法与步骤&#xff1a; 1&#xff1a;利用微软官方提供的MediaCreationT…...

发放优惠券

文章目录 概要整体架构流程技术细节小结 概要 发放优惠券 处于暂停状态&#xff0c;或者待发放状态的优惠券&#xff0c;在优惠券列表中才会出现发放按钮&#xff0c;可以被发放&#xff1a; 需求分析以及接口设计 需要我们选择发放方式&#xff0c;使用期限。 发放方式分…...

【专题刷题】二分查找(二)

&#x1f4dd;前言说明&#xff1a; 本专栏主要记录本人的基础算法学习以及LeetCode刷题记录&#xff0c;按专题划分每题主要记录&#xff1a;&#xff08;1&#xff09;本人解法 本人屎山代码&#xff1b;&#xff08;2&#xff09;优质解法 优质代码&#xff1b;&#xff…...

如何避免IDEA每次打开新项目都重复配置Maven?

每次打开新项目都要重新设置Maven路径&#xff1f;每次导入工程都要手动调整settings.xml&#xff1f;如果你也受够了IDEA这种“健忘”行为&#xff0c;那么这篇文章就是为你准备的&#xff01;今天我们就来彻底解决这个问题&#xff0c;让IDEA记住你的Maven配置&#xff0c;一…...

【Linux网络编程】应用层协议HTTP(实现一个简单的http服务)

目录 前言 一&#xff0c;HTTP协议 1&#xff0c;认识URL 2&#xff0c;urlencode和urldecode 3&#xff0c;HTTP协议请求与响应格式 二&#xff0c;myhttp服务器端代码的编写 HTTP请求报文示例 HTTP应答报文示例 代码编写 网络通信模块 处理请求和发送应答模块 结…...

深度解析之算法之分治(快排)

44.颜色分类 题目链接 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums &#xff0c;原地 对它们进行排序&#xff0c;使得相同颜色的元素相邻&#xff0c;并按照红色、白色、蓝色顺序排列。 我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 必须在不使用库内置…...

【金仓数据库征文】-金仓数据库性能调优 “快准稳” 攻略:实战优化,让数据处理飞起来

我的个人主页 我的专栏&#xff1a; 人工智能领域、java-数据结构、Javase、C语言&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01; 点赞&#x1f44d;收藏❤ 目录 一、KingbaseES金仓数据库简介二、快速入门&#xff1a;金仓数据库下载与安装指南三、“快”…...

DPIN河内AI+DePIN峰会:共绘蓝图,加速构建去中心化AI基础设施新生态

近日&#xff0c;一场聚焦前沿科技融合的盛会——AIDePIN峰会在越南河内成功举办。此次峰会由DPIN、QPIN及42DAO等Web3领域的创新项目联合组织&#xff0c;汇聚了众多Web3行业领袖、技术专家与社区成员。峰会于2025年4月19日举行&#xff0c;其核心议题围绕去中心化物理基础设施…...

vscode和git 踩坑

git init经常 在 vscode push错误问题: 正确姿势&#xff1a;先 GitHub 上建仓库 → git clone 拉到本地 → 再用 VSCode 打开编辑 ❌ 不是&#xff1a;VSCode 里 git init → 再去 GitHub 选个仓库绑定 举个对比 操作流程是否推荐后果GitHub 创建仓库 → git clone → 用 VSC…...

C++11介绍

目录 一、C11的两个小点 1.1、decltype 1.2、nullptr 二、列表初始化 2.1、C98传统的{} 2.2、C11中的{} 2.3、C11中的std::initializer_list 三、右值引用和移动语义 3.1、左值和右值 3.2、左值引用和右值引用 3.3、引用延长生命周期 3.4、左值和右值的参数匹配 3…...

AI数字人:繁荣背后的伦理困境与法律迷局(8/10)

摘要&#xff1a;本文深入剖析 AI 数字人从虚拟走向现实的历程&#xff0c;阐述其融合多技术实现从静态到动态交互的跨越&#xff0c;爆发式应用于各领域带来的商业价值与社会影响&#xff0c;同时直面由此引发的伦理法律挑战&#xff0c;包括身份认同、数据隐私、责任归属及权…...

SOLID 原则在单片机环境下的 C 语言实现示例,结合嵌入式开发常见场景进行详细说明

1. 单一职责原则 (SRP) 定义:一个模块(函数/文件)只负责一个功能。 示例:传感器数据采集与处理分离 // SensorAdc.h - 仅负责ADC原始数据采集 typedef struct { uint16_t (*ReadRaw)(void); // 原始数据读取接口 } SensorAdc; // SensorProcessor.h - 仅负责数据处理…...

RT Thread 发生异常时打印输出cpu寄存器信息和栈数据

打印输出发生hardfault时,当前栈十六进制数据和cpu寄存器信息 在发生 HardFault 时,打印当前栈的十六进制数据和 CPU 寄存器信息是非常重要的调试手段。以下是如何实现这一功能的具体步骤和示例代码。 1. 实现 HardFault 处理函数 我们需要在 HardFault 中捕获异常上下文,…...

SQL 函数进行左边自动补位fnPadLeft和FORMAT

目录 1.问题 2.解决 方式1 方式2 3.结果 1.问题 例如在SQL存储过程中&#xff0c;将1 或10 或 100 长度不足的时候&#xff0c;自动补足长度。 例如 1 → 001 10→ 010 100→100 2.解决 方式1 SELECT FORMAT (1, 000) AS FormattedNum; SELECT FORMAT(12, 000) AS Form…...

Unity中数据和资源加密(异或加密,AES加密,MD5加密)

在项目开发中,始终会涉及到的一个问题,就是信息安全,在调用接口,或者加载的资源,都会涉及安全问题,因此就出现了各种各样的加密方式。 常见的也是目前用的最广的加密方式,分别是:DES、3DES、AES、MD5、XOR(异或) 其中DES、3DES、AES、MD5用在数据加密中偏多,特别是…...

C++初窥门径

const关键字 一、const关键字 修饰成员变量 常成员变量&#xff1a;必须通过构造函数的初始化列表进行初始化&#xff0c;且初始化后不可修改。 示例&#xff1a; class Student { private: const int age; // 常成员变量 public: Student(string name, int age) : age(ag…...

Spring知识点总结

目录 1.什么是spring&#xff1f;你对spring的理解&#xff1f; 2.spring的优缺点&#xff1f; 3.解释一下IOC和AOP&#xff1f; 4.IOC和DI的区别&#xff1f; 5.spring中管理对象注入的方式&#xff1f; 6.自动注入的注解有哪些&#xff1f; 声明bean的注解 Bean的生命…...

Oracle_开启归档日志和重做日志

在Oracle中&#xff0c;类似于MySQL的binlog的机制是归档日志&#xff08;Archive Log&#xff09;和重做日志&#xff08;Redo Log&#xff09; 查询归档日志状态 SELECT log_mode FROM v$database; – 输出示例&#xff1a; – LOG_MODE – ARCHIVELOG (表示已开启) – NO…...

【金仓数据库征文】-数据库界新兴前列者,本篇带你速懂金仓数据库!

最近写课程设计、搞毕设是不是被数据库折腾到崩溃&#xff1f;动不动就报错、数据迁移还超麻烦&#xff01;今天挖到个宝藏 —— 国产金仓数据库 KingbaseES&#xff0c;操作超简单&#xff0c;还自带 “翻译器” 帮你迁移数据&#xff01;性能强还稳定&#xff0c;关键完全免费…...

人工智能与机器学习,谁是谁的子集 —— 再谈智能的边界与演进路径

人工智能&#xff08;Artificial Intelligence, AI&#xff09;作为当代最具影响力的前沿技术之一&#xff0c;常被大众简化为 “深度学习” 或 “大模型” 等标签。然而&#xff0c;这种简化认知往往掩盖了AI技术内部结构的复杂性与多样性。事实上&#xff0c;AI并非单一方法的…...

Linux进程学习【进程状态】

&#x1f33c;&#x1f33c;前言&#xff1a;在操作系统中&#xff0c;进程是最基本的资源管理单位&#xff0c;而操作系统通过精确管理这些进程的状态来确保系统能够高效运行。进程的状态不仅仅是操作系统设计的一部分&#xff0c;它对系统的性能、稳定性以及资源的分配起着至…...

用 ESP32 模拟 Wiegand 刷卡器:开发门禁系统必备的小工具

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…...

什么是 MCP?与 AI Agent 的关系是什么?

首先先回答一下什么是MCP&#xff1f; 如果你经常使用像Claude这样的大语言模型&#xff0c;你可能已经注意到它们虽然强大&#xff0c;但有时候也有局限性&#xff0c;比如无法获取实时信息或访问特定工具。 模型上下文协议&#xff08;Model Context Protocol&#xff0c;简…...

Python ZIP文件操作全解析:从基础压缩到高级技巧

目录 一、ZIP文件操作基础三板斧 1.1 创建压缩包 1.2 解压操作 1.3 文件遍历与信息获取 二、进阶技巧&#xff1a;让压缩更智能 2.1 加密压缩实战 2.2 增量更新策略 2.3 性能优化技巧 三、高级场景解决方案 3.1 分卷压缩实现 3.2 跨平台路径处理 3.3 异常处理最佳实…...

Linux:进程的等待

当以一个进程结束时&#xff0c;它会变成僵尸进程&#xff0c;这个僵尸进程如果不处理&#xff0c;就会一直占用CPU资源&#xff0c;如果父进程要回收这个进程会通过进程等待的方式处理&#xff0c;回收子进程只会&#xff0c;会得到进程的退出信息 进程等待 父进程通过进程等…...