余晖落尽暮晚霞,黄昏迟暮远山寻
本站
当前位置:网站首页 > 编程知识 > 正文

Swift 的错误处理(关于swift)

xiyangw 2022-12-03 11:54 22 浏览 0 评论

Swift的错误处理是该语言的独特功能。它看起来很像其他语言中的异常,但语法不完全相同,它也不尽如人意。今天我要看看Swift错误在内部工作。

语义

Swift 的错误处理(关于swift)

我们先来看一下Swift错误如何在语言层面上工作。

任何Swift函数都可以使用throws关键字进行装饰,这表明它可以引发错误:

func getStringMightFail()throws - > String {...

要从这样的一个函数中抛出错误,请使用符合Error协议的值的throw关键字:

抛出MyError.brainNotFound

调用throws函数时,必须包含try关键字:

let string = try getStringMightFail()

try关键字不执行任何操作,但它是一个必需的标记,表示该函数可能会引发错误。调用必须在允许抛出错误的上下文中,无论是在throws函数中还是在带有catch处理程序的do块中。

要写一个catch处理程序,将try调用放在一个do块中,并添加一个catch块:

做{

let string = try getStringMightFail()

...

} catch {

print(“发生错误:\(错误)”)

}

当抛出错误时,执行跳转到catch块。抛出的值可用错误。您可以通过类型检查和条件以及多个catch子句来获得想法,但这些都是基础知识。有关所有详细信息的详细信息,请参阅Swift编程语言的错误处理部分。

这就是它的作用。它是如何工作的?

履行

为了找出它是如何工作的,我写了一些虚拟代码与错误处理我可以反汇编:

struct MyError:Error {

var x:Int

var y:Int

var z:Int

}

func投掷者(x:Int,y:Int,z:Int)throws - > Int {

抛出MyError(x:x,y:y,z:z)

}

func捕手(f:(Int,Int,Int)throws - > Int){

做{

让x =尝试f(1,2,3)

print(“Received \(x)”)

} catch {

print(“Caught \(error)”)

}

}

当然,现在Swift是开源的,我可以直接看看编译器的代码,看看它的作用。但这不是乐趣,而且这更容易。

事实证明,Swift 3和Swift 4做的不一样。我将简要介绍一下Swift 3,然后再来看看Swift 4,因为这是即将到来的。

Swift 3的工作原理是自动化Objective-C的NSError约定。编译器插入一个额外的隐藏参数,这个参数基本上是Error *或NSError **。抛出错误包括将错误对象写入该参数中传递的指针。调用者分配一些堆栈空间并在该参数中传递其地址。返回时,它会检查该空间是否现在包含错误。如果是,它跳到catch块。

斯威夫特4获得了一个好心人。基本思想是一样的,但是除了正常的额外参数之外,还会为错误返回保留一个特殊的寄存器。以下是Thrower中的相关汇编代码:

调用imp___stubs__swift_allocError

mov qword [rdx],rbx

mov qword [rdx + 8],r15

mov qword [rdx + 0x10],r14

mov r12,rax

这将调用Swift运行时分配一个新的错误,用相关的值填充它,然后把指针放在r12中。然后它返回给呼叫者。 Catcher中的相关代码如下所示:

叫r14

mov r15,rax

测试r12,r12

je loc_100002cec

它进行呼叫,然后检查r12是否包含任何内容。如果是,它跳到catch块。 ARM64上的技术几乎相同,x21寄存器用作错误指针。

在内部,它看起来很像返回Result类型,或者返回某种错误代码。 throws函数在特殊的地方将调用者的抛出错误返回给调用者。调用者检查该位置是否存在错误,如果是,则跳转到错误处理代码。生成的代码看起来类似于使用NSError **参数的Objective-C代码,实际上Swift 3的版本是相同的。

与异常比较

在讨论其错误处理系统时,Swift非常谨慎,不要使用“异常”这个词,但它看起来很像其他语言的例外。它的实现如何比较?有很多语言有例外,其中许多语言做的不同,但自然的比较是C ++。 Objective-C异常(尽管它们确实存在,尽管没人使用它们)在现代运行时使用C ++的异常机制。

充分探索C ++异常如何工作可以填写一本书,所以我们必须解决一个简短的描述。

调用throw函数(这是C ++函数的默认值)的C ++代码正好像调用非抛出函数一样生成程序集。也就是说,它传递参数并检索返回值,没有考虑例外的可能性。这怎么可能工作?除了生成无异常代码之外,编译器还生成一个表,其中包含有关代码如何(以及是否)处理异常的信息,以及如何在抛出异常的情况下如何安全地展开堆栈以退出函数。当某些功能引发异常时,它会爬起堆栈,查找每个函数的信息,并使用它来将堆栈解压缩到下一个函数,直到找到异常处理程序或运行结束。如果它找到一个异常处理程序,它将控制权转移到该处理程序,然后在catch块中运行代码。有关C ++异常如何工作的更多信息,请参阅C ++ ABI for Itanium:异常处理。该系统被称为“零成本”异常处理。术语“零成本”是指当没有抛出异常时会发生什么。因为该代码的编译完全与没有例外一样,因此不支持异常的运行时开销。调用潜在投掷函数与调用不抛出函数一样快,并且将try块添加到代码中并不会在运行时完成任何额外的工作。当抛出异常时,“零成本”的概念出现在窗口之外。使用表解开堆栈是一个昂贵的过程,需要大量的时间。该系统围绕着很少抛出异常的想法进行设计,并且在没有抛出异常的情况下的性能更重要。这个假设在几乎所有的代码中都可能是真实的。相比之下,Swift的系统非常简单。它不会为throws和non-throws函数生成相同的代码。相反,每次调用throws函数后都要检查是否返回错误,如果是这样,则跳转到相应的错误处理代码。这些检查不是免费的,虽然它们应该很便宜。对于Swift来说,权衡是非常有意义的。 Swift错误看起来很像C ++异常,但实际上它们的用法不一样。几乎任何C ++调用都可能会抛出,甚至像新操作符这样的基本的东西也会被抛出来,以指示一个错误。在每次调用之后,明确地检查抛出的异常将添加大量额外的检查。相比之下,几个Swift电话在典型的代码库中被标记为throws,因此显式检查的成本很低。结论Swift的错误处理请求与其他语言(例如C ++)中的异常进行比较。 C ++的异常处理在内部非常复杂,但Swift采取不同的方法。 Swift在常见的情况下,不用放松表来实现“零成本”,而是在特殊寄存器中返回抛出的错误,而调用者检查该寄存器以查看是否已经抛出错误。当错误不被抛出时,这增加了一些开销,但是避免了使C ++做的事情变得非常复杂。编写Swift代码将会非常努力,错误处理的开销会产生明显的差异。

相关推荐

前后端分离 Vue + NodeJS(Koa) + MongoDB实践

作者:前端藏经阁转发链接:https://www.yuque.com/xwifrr/gr8qaw/vr51p4写在前面闲来无事,试了一下Koa,第一次搞感觉还不错,这个项目比较基础但还是比较完整了,...

MongoDB 集群如何工作?

一、什么是“MongoDB”?“MongoDB”是一个开源文档数据库,也是领先的“NoSQL”数据库,分别用“C++”“编程语言”编写,使用带有“Schema”的各种类似JSON的文档,是也分别被认为...

三部搭建mongo,和mongo UI界面

三步搭建mongo,和mongoUI界面安装首先你需要先有一个docker的环境检查你的到docker版本docker--versionDockerversion18.03.1-ce,b...

Mongodb 高可用落地方案

此落地方案,用于实现高可用。复制集这里部署相关的复制集,用于实现MongoDB的高可用。介绍MongoDB复制集用于提供相关的数据副本,当发生硬件或者服务中断的时候,将会从副本中恢复数据,并进行自动...

一次线上事故,我顿悟了MongoDB的精髓

大家好,我是哪吒,最近项目在使用MongoDB作为图片和文档的存储数据库,为啥不直接存MySQL里,还要搭个MongoDB集群,麻不麻烦?让我们一起,一探究竟,继续学习MongoDB分片的理论与实践,...

IDEA中安装MongoDB插件-再也无要nosql manager for mongodb

大家都知道MongoDB数据库作为典型的非关系型数据库被广泛使用,但基于MongoDB的可视化管理工具-nosqlmanagerformongodb也被用的较多,但此软件收费,所以国内的破解一般...

数据库监控软件Lepus安装部署详解

Lepus安装部署一、软件介绍Lepus是一套开源的数据库监控平台,目前已经支持MySQL、Oracle、SQLServer、MongoDB、Redis等数据库的基本监控和告警(MySQL已经支持复...

YAPI:从0搭建API文档管理工具

背景最近在找一款API文档管理工具,之前有用过Swagger、APIManager、Confluence,现在用的还是Confluence。我个人一直不喜欢用Swagger,感觉“代码即文档”,让代...

Mac安装使用MongoDB

下载MongoDB包:https://www.mongodb.com/download-center解压mongodb包手动解压到/usr/local/mongodb文件夹配置Mac环境变量打开环境...

保证数据安全,不可不知道的MongoDB备份与恢复

大家在项目中如果使用MongoDB作为NOsql数据库进行存储,那一定涉及到数据的备份与恢复,下面给大家介绍下:MongoDB数据备份方法在MongoDB中我们使用mongodump命令来备...

MongoDB数据备份、还原脚本和定时任务脚本

备注:mongodump和mongorestore命令需要在MongoDB的安装目录bin下备份脚本备份格式/usr/local/mongodb/bin/mongodump -h ...

等保2.0测评:mongoDB数据库

一、MongoDB介绍MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB是一个介于关系数据库和非关系数据库之间的产...

MongoDB入门实操《一》

什么是MongoDBMongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB是一个介于关系数据库和非关系数据库之...

Python安装PyMongo的方法详细介绍

欢迎点击右上角关注小编,除了分享技术文章之外还有很多福利,私信学习资料可以领取包括不限于Python实战演练、PDF电子文档、面试集锦、学习资料等。前言本文主要给大家介绍的是关于安装PyMongo的...

第四篇:linux系统中mongodb的配置

建议使用普通用户进行以下操作。1、切换到普通用户odysee。2、准备mongodb安装包,自行去官网下载。3、解压安装包并重命名为mongodb4.04、配置mongodbcdmongod...

取消回复欢迎 发表评论: