在本文中,我们将给您介绍关于Swiftdo-try-catch语法的详细内容,并且为您解答swiftdocatch的相关问题,此外,我们还将为您提供关于''try(Aa=newA())''VS''tr
在本文中,我们将给您介绍关于Swift do-try-catch语法的详细内容,并且为您解答swift do catch的相关问题,此外,我们还将为您提供关于''try(A a = new A())'' VS ''try finally''、C++反汇编第五讲,认识C++中的Try catch语法,以及在反汇编中还原、delphi try except语句 和 try finally语句用法、delphi try except语句 和 try finally语句用法以及区别的知识。
本文目录一览:- Swift do-try-catch语法(swift do catch)
- ''try(A a = new A())'' VS ''try finally''
- C++反汇编第五讲,认识C++中的Try catch语法,以及在反汇编中还原
- delphi try except语句 和 try finally语句用法
- delphi try except语句 和 try finally语句用法以及区别
Swift do-try-catch语法(swift do catch)
我尝试理解Swift 2中新的错误处理方法。这是我做的:我首先声明了一个错误枚举:
enum SandwichError: ErrorType { case NotMe case DoItYourself}
然后我声明了一个引发错误的方法(伙计们不是异常。这是一个错误。)。这是该方法:
func makeMeSandwich(names: [String: String]) throws -> String { guard let sandwich = names["sandwich"] else { throw SandwichError.NotMe } return sandwich}
问题出在呼叫方。这是调用此方法的代码:
let kitchen = ["sandwich": "ready", "breakfeast": "not ready"]do { let sandwich = try makeMeSandwich(kitchen) print("i eat it \(sandwich)")} catch SandwichError.NotMe { print("Not me error")} catch SandwichError.DoItYourself { print("do it error")}
之后,do
行编译器说Errors thrown from here are not handled because the enclosingcatch is not exhaustive
。但是我认为这是详尽无遗的,因为SandwichError
枚举中只有两种情况。
对于常规的switch语句,swift可以理解,在处理每种情况时,它都是详尽的。
答案1
小编典典Swift 2错误处理模型有两个重要方面:详尽性和弹性。它们一起归结为您的do
/catch
语句,需要捕获所有可能的错误,而不仅仅是您知道可以抛出的错误。
请注意,您并未声明函数会抛出什么类型的错误,仅声明它是否会抛出任何类型的错误。这是一个零一无穷的问题:当有人为他人(包括您将来的自己)定义一个函数供您使用时,您不必让每个函数的客户都适应您实现中的每一个变化功能,包括它可能引发的错误。您希望调用您的函数的代码能够适应这种变化。
因为您的函数无法说出它抛出的错误类型(或将来可能抛出的错误),所以catch
捕获该错误的块不知道它可能抛出的错误类型。因此,除了处理您所知道的错误类型之外,您还需要使用通用catch
语句来处理那些您不知道的错误类型-
这样,如果您的函数更改了将来抛出的错误集,则调用方仍将捕获该错误类型错误。
do { let sandwich = try makeMeSandwich(kitchen) print("i eat it \(sandwich)")} catch SandwichError.NotMe { print("Not me error")} catch SandwichError.DoItYourself { print("do it error")} catch let error { print(error.localizedDescription)}
但是,我们不要就此止步。再考虑一下这种弹性思想。设计三明治的方式必须在使用它们的每个地方描述错误。这意味着,每当更改错误案例集时,都必须更改使用它们的每个位置……不是很有趣。
定义自己的错误类型的想法是让您集中诸如此类的事情。您可以description
为错误定义一个方法:
extension SandwichError: CustomStringConvertible { var description: String { switch self { case NotMe: return "Not me error" case DoItYourself: return "Try sudo" } }}
然后,您的错误处理代码可以要求您的错误类型进行自我描述-现在,您处理错误的每个地方都可以使用相同的代码,并且还可以处理将来可能发生的错误情况。
do { let sandwich = try makeMeSandwich(kitchen) print("i eat it \(sandwich)")} catch let error as SandwichError { print(error.description)} catch { print("i dunno")}
这也为错误类型(或错误扩展)支持其他报告错误的方式铺平了道路-
例如,您可以在错误类型上拥有扩展名,该扩展名知道如何向UIAlertController
iOS用户报告错误。
''try(A a = new A())'' VS ''try finally''
实现了AutoCloseable接口的类,可以在try的时候直接实例化对象。try代码块完成之后,自动调用close方法,相当于在finally里主动调用。但是出现异常后的流程和try finally有什么不同呢? 下面写代码测试一下。
首先定义一个类Cat,实现AutoCloseable接口
class Cat implements AutoCloseable{
void sayHello() throws Exception {
Utils.println("calling sayHello(), I will throw an exception");
throw new Exception("Exception in sayHello() ");
}
@Override
public void close() throws Exception {
Utils.println("I''m closing, I will throw an exception");
throw new Exception("Exception in close()");
}
}
我们的这个Cat有以下特点:
- sayHello方法会抛出异常
- close方法也会抛出异常
test v1: ''try(Cat cat = new Cat())'' VS ''try finally''
没有catch(不要被外层的catch迷惑,那只是为了打印异常)
static void testV1(){
Utils.println("----try(Cat cat = new Cat())-----");
try{
try(Cat cat = new Cat()){
cat.sayHello();
}
}catch (Exception e){
Utils.println("cache error in main (" + e + "), let''s see its stack trace");
Utils.printStackTrace(e);
}
Utils.println("--------------");
Utils.println("----try finally-----");
try{
Cat cat = null;
try{
cat = new Cat();
cat.sayHello();
}finally {
if(cat != null){
cat.close();
}
}
}catch (Exception e){
Utils.println("cache error in main (" + e + "), let''s see its stack trace");
Utils.printStackTrace(e);
}
Utils.println("--------------");
}
结果输出:
----test v1----------------------------------------
----try(Cat cat = new Cat())-----
calling sayHello(), I will throw an exception
I''m closing, I will throw an exception
cache error in main (java.lang.Exception: Exception in sayHello() ), let''s see its stack trace
java.lang.Exception: Exception in sayHello()
at Cat.sayHello(Cat.java:4)
at Test.testV1(Test.java:16)
at Test.main(Test.java:4)
Suppressed: java.lang.Exception: Exception in close()
at Cat.close(Cat.java:10)
at Test.testV1(Test.java:17)
... 1 more
--------------
----try finally-----
calling sayHello(), I will throw an exception
I''m closing, I will throw an exception
cache error in main (java.lang.Exception: Exception in close()), let''s see its stack trace
java.lang.Exception: Exception in close()
at Cat.close(Cat.java:10)
at Test.testV1(Test.java:33)
at Test.main(Test.java:4)
--------------
结论
- try(Cat cat = new Cat())
- try代码块完成之后会自动调用close
- close抛出的异常,被Suppressed了,外层捕获的只有sayHello的异常,但通过堆栈可以找到这个Suppressed的异常
- try finally
- 外层捕获的是在finally执行close时抛出的异常,sayHello的异常完全不见了。
test v2: ''try(Cat cat = new Cat()) catch{}'' VS ''try catch finally''
有catch,并且catch里再抛出异常
static void testV2(){
Utils.println("----try(Cat cat = new Cat()) catch-----");
try{
try(Cat cat = new Cat()){
cat.sayHello();
} catch (Exception e) {
Utils.println("cached err (" + e.getMessage() + "), I will throw an exception again");
throw new Exception("Exception in catch", e);
}
}catch (Exception e){
Utils.println("cache error in main (" + e + "), let''s see its stack trace");
Utils.printStackTrace(e);
}
Utils.println("-----------------------------------------");
Utils.println("----try catch finally--------------------");
try{
Cat cat = null;
try{
cat = new Cat();
cat.sayHello();
} catch (Exception e) {
Utils.println("cached err (" + e.getMessage() + "), I will throw an exception again");
throw new Exception("Exception in catch", e);
}finally {
if(cat != null){
cat.close();
}
}
}catch (Exception e){
Utils.println("cache error in main (" + e + "), let''s see its stack trace");
Utils.printStackTrace(e);
}
Utils.println("-------------------------------------------");
}
结果输出
----test v2------
----try(Cat cat = new Cat()){} catch{}-----
calling sayHello(), I will throw an exception
I''m closing, I will throw an exception
cached err (Exception in sayHello() ), I will throw an exception again
cache error in main (java.lang.Exception: Exception in catch), let''s see its stack trace
java.lang.Exception: Exception in catch
at Test.testV2(Test.java:50)
at Test.main(Test.java:8)
-----------------------------------------
----try catch finally--------------------
calling sayHello(), I will throw an exception
cached err (Exception in sayHello() ), I will throw an exception again
I''m closing, I will throw an exception
cache error in main (java.lang.Exception: Exception in close()), let''s see its stack trace
java.lang.Exception: Exception in close()
at Cat.close(Cat.java:10)
at Test.testV2(Test.java:70)
at Test.main(Test.java:8)
-------------------------------------------
---------------------------------------------------------------------
结论
- try(Cat cat = new Cat()) catch
- catch之前就调用了close(符合try代码块完成之后会自动调用close这个结论)
- catch到的是sayHello的异常,close抛出的异常依然被Suppressed了
- catch中再次抛出的异常被外层捕获
- try catch finally
- 先走catch,再走finally,所以catch捕获的是sayHello的异常
- catch中再次抛出的异常不见了,外层捕获的是在finally执行close时抛出的异常。
测试代码地址:https://github.com/kongxiangxin/pine/tree/master/auto-closeable
C++反汇编第五讲,认识C++中的Try catch语法,以及在反汇编中还原
我们以前讲SEH异常处理的时候已经说过了,C++中的Try catch语法只不过是对SEH做了一个封装.
如果不懂SEH异常处理,请点击博客链接熟悉一下,当然如果不想知道,也可以直接往下看.因为异常处理所以做了封装,但是不影响我们还原.
这里有两种解决方法,
第一种,小白也能明白了还原方式,不用懂原理
第二种,了解其原理,并能在IDA中正确的还原.
SEH异常处理博客链接:
http://www.cnblogs.com/iBinary/category/1083755.html
一丶小白也懂的异常处理还原.
第一种,不用懂任何原理,(反汇编要懂,最起码的汇编代码知道是什么,不然这个专题讲了你也看不懂)
先看下高级代码:
int main(int argc,char* argv[]) { try { throw 3;//抛出3整形的异常 } catch (int) { printf("%d\r\n",3); } return 0; }
OD调试,观看步骤.
首先步骤分两步.
1.找SEH异常处理回调.
2.找参数多的call下断点
3.最后一个是call 寄存器.则找到正确的cath位置.
1.找到SEH的异常处理回调函数(如果不懂,看下SEH的筛选器异常.)
观看栈参数,可以看到回调函数地址是00410CC0,此时反汇编窗口跟过去下断点.
2.观看参数多了call,下断点,然后跟进.
因为层级较多,这里大家动手实战即可.
3.找到最后一层call一个寄存器.
此时则找到了我们的cath处理块了.
二丶理解原理进行实战.
上面说的,不懂原理你也可以做.比如以后工作了,原理不懂,起码做代码还原的时候还可以混口饭吃 ^_^
下面讲解原理.
首先,我们先寻找数据关系.
一个函数可以有多个 try 这是没问题的,所以 函数和try的关系是一对多的关系.
一个try有多个catch也是没有问题的.那么对应关系也是一对多.
所以操作系统为了管理这些.需要建表.(当然是未公开的),我们可以逆向
1.原理介绍,上半部分表
观看表
看到怎么多表是不是很晕.其实很简单,只是里面的某个字段对我们有用.
1.观看函数信息表FuncInfo,重要字段就是dwTryCount,以及pTryBlockMap,我们说过一个函数可以有多个try,所以函数信息就记录了try的个数.以及每个try的try块结构,关于上面的成员,都是SEH的异常展开的.要做首尾动作的,对于我们还原没有任何阻碍,可以不用理解.
2.TryBlockMap表(tyr块信息表),我们还说过,一个try可以有多个catch,显然,try块信息表也要记录catch的个数.一个catch信息块的结构.
3.cathch信息块的结构体(msRTTIDsrc)msRTTIDsrc这个表是IDA识别的,我们可以自己说他是catch信息表,msRTTIDsrc的全名是 Microsoft Run Time TypeInfo ....微软运行时类型识别.
表结构体中重要字段就是 dwCount,catch信息快的个数,一个cathch信息表.
4.catch信息表(msRTTIDsrc),里面有4个成员,nflag 一个标志,表示你是常量,还是变量,还是引用. ptype,表示你的类型是什么类型.是int,还是float什么的,这个有个专门的表格存放着.下面重要字段则是catch的函数地址.编译器内部编译的时候,编译的catch是一个函数,也是有返回值的,返回值是catch_end的位置.
到这里,我们的上半部分就看完了.
总结一下:
对于上半部分.主要着重于 函数信息表,try块表.catch表.以及catch块表.
为什么说上半部分,是这样的,对于我们还原来说.有两种情况.
1.完整的还原trycatch的异常信息结构
2.找到关键的catch匹配函数.
这两种是完全不一样的,如果我们还原就看上版本的表.如果我们要找那个catch捕获异常,则看下部分的表,(下面讲解.)
实战演练.
实战演练的时候,我们就要知道函数信息表在哪,其实我们已经找到了,只不过大家不知道,按照小白思路为什么一路跟就可以找到catch块表.只是我们没讲.
1.找到注册异常回调的地方,进入回调函数内部.
2.看到反汇编.
这个地方,给eax赋值的地址就是函数信息表了.我们用IDA打开.根据表结构可以很自然的就能找到.catch块的位置.
IDA实战.
1.找到函数信息表点击进去
可以看到MaicNumber等等一些列的东西.
,通过最后一个成员,可以找到Try块信息表.
2.找到Try块信息表
可以看到Try块信息表中有几个Catch信息.
3.找到Catch信息表.
看到最后是catch的回调地址,里面则是catch的位置.
我们也能看到类型是什么.自己点击进去看看即可.
4.找到Catch函数地址,点击查看.
正确找到了Catch块了.
2.下半部分表格详解.
上面的部分是针对我们还原做的.下半部分主要就是找我要快速定位这个异常是谁接受的,那个catch块处理的.
第一个表 异常抛出表,重要字段catch数组表
第二个表是个数组表,一个throw对应多个catch,所以有个数组,这个数组是异常匹配表.表明了有多少个catch可以匹配.
一个记录个数,第二个成员则是二级指针.其内容是一个地址,其地址是一个cathc信息块的结构.
实战演练.
关于异常抛出表要怎么寻找,还记得的我们的高级代码有一个 throw吗?,其位置就是抛出异常表的位置.
关于抛出异常,我们需要了解的知识.当我们抛出一个常量或者变量的时候,不管怎么样,都会建立一个内存单元来接受我们抛出的值.所以别看你抛出的是常量,其实也成为内存单元了,也相当于一个变量了.
1.找到异常信息表.
@H_51_301@
最后一个成员是catch表.这个表保存了可以匹配的catch有多少个.
2.找到catch异常信息匹配表.
可以看出,值为1,下面是一个catch表,表明了有一个匹配的.
3.找到catch信息表.
通过异常信息表的第二个参数,也就是类型表,可以看是哪个匹配的.而且对类型表做一个引用,看谁引用类类型表,则能找到catch的函数地址.当然这一步是还原的动作.
4.找到类型表.对类型表做一个交叉引用.
如果引用显示的太少了,可以自己百度, IDA引用数量调整.看怎么设置的,或者当前位置按 x键查看.
如果按x,跳过去的是try块表,你需要通过try块表可以直接查看.那个catch信息表.
delphi try except语句 和 try finally语句用法
总结
以上是小编为你收集整理的delphi try except语句 和 try finally语句用法全部内容。
如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。
delphi try except语句 和 try finally语句用法以及区别
总结
以上是小编为你收集整理的delphi try except语句 和 try finally语句用法以及区别全部内容。
如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。
关于Swift do-try-catch语法和swift do catch的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于''try(A a = new A())'' VS ''try finally''、C++反汇编第五讲,认识C++中的Try catch语法,以及在反汇编中还原、delphi try except语句 和 try finally语句用法、delphi try except语句 和 try finally语句用法以及区别等相关知识的信息别忘了在本站进行查找喔。
本文标签: