C# to IL 10 Exception Handling(异常处理)
Exception handling in IL is a big let down. We expected a significant amount of complexity,
but were proved wrong, right from the beginning. IL cannot be termed as a machine level
assembler. It actually has a number of directives like try and catch, that work like their
higher level counterparts(副本).
In the above example, the function abc first creates an object that looks like Exception
using newobj and places it on the stack. Thereafter the throw instruction throws an
exception. This Exception is placed on the stack, hence the catch instruction is called. In
the catch instruction, e, a local varaible, is an instance of Exception. The next instruction,
leave.s jumps to label IL_001e, the label is beyond the catch.
To exit off from a try or a catch block, instead of the branch instruction br, leave is used.
The reason is that we are dealing with exceptions, which are to be handled in a special
way in IL. Exception handling in IL is done using higher level instructions.
The above program has utilised a try catch without a parameter and a finally clause.
Adding a finally clause associates the same try with a catch, and a finally. In a sense, two
copies of try are created, one for catch and the other for finally.
If the catch directive is not supplied with an Exception object, it will take an object that
looks like System.Object. In the catch, the item is popped of the stack, as its value holds
no significance. The string is printed before the leave. Also, along with try-catch is the
finally clause which is the next to be executed. A finally is executed as a separate try finally
directive and it can only be exited using the endfinally instruction.
Nowhere is it specified that a try must have a catch. A finally will ultimately be called at
the end of the try.
In the absence of a try catch block, if function abc throws an exception, it will not get
caught. Instead, a runtime error is generated. A try catch clause is recommended to
proactively catch the exception, otherwise when an exception is thrown and the program
will come to a grinding halt.
The above program is quite lengthy, but very simple. It proves the fact that code placed in a
finally block is always executed. Like death and taxes, a finally cannot be avoided.
The for statement branches to label IL_0032 where we first check for the value to be less
than or equalto10. If it results in TRUE, the code at label IL_0006 is executed. A we learnt
in one of the earlier chapters, the condition check for the for statement is always placed at
the bottom in IL.
In the first attempt, string "1 try" is printed . Thereafter the code within the second try is
executed, where "2 try" is printed. The break statement in C# gets converted to a leave to
label IL_0037 in IL. This label signifies the end of the for statement. The leave instruction is
smart enough to realize that it is located within two trys with a finally clause, hence it calls
the code with the finally instruction.
Under normal circumstances, break becomes a branch instruction if not placed within trycatch.
The lock keyword ensures that while one thread executes a function, the other threads
remain suspended. This keyword gets translated into a large amount of IL code. In fact, it
generates the maximum amount of code amongst all the keywords.
The C# compiler first calls the static function Enter from the Monitor class. Then, it
executes the code located in a try. The try block here contains no code. On encountering
the leave instruction, the program enters the finally which calls the Exit function from the
Monitor class. This initiates another thread that is waiting at the Enter function.
Whenever an exception occurs, an object representing the exception must be created. This
exception object has to be a class derived from Exception and cannot be a value type or a
pointer.
A Structured Exception Handling (SEH) block is made up of a try and one or more
handlers. A try directive is used to declare a protected block.
We cannot exit from a protected block with a ret but, on using it, no errors are generated at
assemble time or run time. As a rule, only a leave or a throw to another exception is
acceptable to exit from a protected block. A leave statement is permitted in the try and not
in the catch.
We can nest as many trys or protected blocks within each other. A leave is required at the
end of every try to avoid all errors.
We can have four types of handlers for a try or a protected block. They are:
• finally
• catch
• fault
• filter
Only one of it can be used at a time
If we comment out the code where the function abc has been called, we get the following
output:
As mentioned earlier, the protected block can only be handled by a single handler.
In the above example, when an exception is thrown, the catch is called and not finally as it
does not have its own try directive. The runtime does not give us any error, but it ignores
the finally handler.
If, however, no exception is thrown, as is the case when we comment out the call of the
function abc, then the finally gets called.
It is quaint that the try is a directive, but the handler is not. We have two classes of
handlers:
• exception resolving handlers
• exception observing handlers.
The finally and fault handlers are exception observing handlers as they do not resolve the
exception.
In an exception resolving handler, we try and resolve the exception so that normal program
control continues. The catch and filter handlers are examples of such handlers.
The deepest handler will be visited first, followed by the next enclosing one and so on, until
we find an appropriate handler. A handler has its own instructions, using which, the
program can exit a handler. It is illegal to use any other instruction for this purpose, but at
times the assembler is unable to detect this misfit.
We are not allowed to jump off a catch handler. It is essential to leave the handler in an
orderly manner only
If we comment out the call of the function abc, we get an error, a Windows error, which is
incomprehensible. The purpose of the above program is to demonstrate that we can use
labels to delimit code in a protected block. Thereafter, we can use the try directive,
indicating to it the start and end label of our code and also the start and end of the fault
handler. This is another way of utilising the try directive.
The catch keyword creates a type filtered exception. Whenever an exception occurs in a
protected block, the EE checks whether the exception that occurred earlier, is equal to or a
sub-type of the error that the catch expects. If the type matches, the code of the catch is
called. If the type does not match, the EE will continue to search for another handler
The program is not allowed to resume execution after an exception occurs. This means
that, we cannot go back to the protected block where the exception took place. In this case,
we are allowed to do so, but keep in mind that we were using a beta copy of the assembler.
Whenever the EE sees a leave in a catch block, it knows that the exception is done with,
and the system returns to a normal state.
Here, at the end of the catch is the rethrow instruction, which rethrows the same
exception again. As there is no other catch block to catch the exception, the exception is
thrown at run time.
Here, we placed another try directive with a separate catch. The exception that is thrown
by the inner catch, cannot be caught by another catch at the same level. It needs to be
caught by the catch at the higher level. Thus one more catch is needed.
The C# compiler watches our code like a hawk. On the other hand, the assembler is a blind
bat.
There are two exception handlers:
• IOException: This handles Input/Output Exceptions.
• Exception: This is a generic handler that handles generic exceptions since all
exceptions are derived from exception.
Consciously, we have placed the generic Exception handler first. Therefore, irrespective of
the exception thrown, the second handler will never get called. The function abc now
throws a IOException. The generic Exception handler, which is placed earlier in the code,
is encountered first, and therefore, it deals with the exception. The C# compiler would have
generated an error in this situation, but the assembler assumes what you are conscious of
your deeds.
The above exception is thrown when there is no leave in a catch and there is another catch
following this one. In one of our earlier programs above, we have used only a single catch.
The last type of fault handler, which is the most generic, either does not seem to work or it
could also mean that we have done something wrong
We use the keyword filter with a label, which denotes the start point of some code. This
code checks whether the exception must be handled or not. This is triggered off by placing
either the number 0 or 1 on the stack. In our case, none of the code dealing with the filter
gets called.
C# to IL 10 Exception Handling(异常处理)的更多相关文章
- Exception handling 异常处理的本质
异常处理的本质:状态回滚或者状态维护. https://en.wikipedia.org/wiki/Exception_handling In general, an exception breaks ...
- OAF_OAF Exception Handling异常处理(概念)
2014-06-12 Created By BaoXinjian
- 异常处理与MiniDump详解(3) SEH(Structured Exception Handling)
write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie 讨论新闻组及文件 一. 综述 SEH--Structured Exception Handlin ...
- C#编程.异常处理(Exception Handling Statements)
C#语言包含结构化异常处理(Structured Exception Handling,SEH). throw The throw statement is used to signal the oc ...
- Exception Handling in ASP.NET Web API webapi异常处理
原文:http://www.asp.net/web-api/overview/error-handling/exception-handling This article describes erro ...
- 黄聪:Microsoft Enterprise Library 5.0 系列教程(七) Exception Handling Application Block
原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(七) Exception Handling Application Block 使用企业库异常处理应用程序模块的 ...
- Exception Handling引入MVP
异常处理(Exception Handling)是所有系统的最基本的基础操作之一,其它的比如日志(Logging).审核(Auditing).缓存(Caching).事务处理(Transaction) ...
- Unity、Exception Handling引入MVP
什么是MVP?在“MVP初探”里就有讲过了,就是一种UI的架构模式. 简单的描述一下Unity和Exception Handling Application Block: Unity是一个轻量级的可扩 ...
- [转]java-Three Rules for Effective Exception Handling
主要讲java中处理异常的三个原则: 原文链接:https://today.java.net/pub/a/today/2003/12/04/exceptions.html Exceptions in ...
随机推荐
- 1.6socket服务器传送文件--gui窗口
socket服务器代码 import sys,os,time,_thread from socket import * class Server(object): def __init__(self) ...
- Zynq-PL中创建AXI Master接口IP及AXI4-Lite总线主从读写时序测试(转)
转载:原文 http://www.eefocus.com/antaur/blog/17-08/423751_6cc0d.html 0. 引言 通过之前的学习,可以在PL端创建从机模式的AXI接口IP ...
- sptring boot 修改默认Banner
一.自定义banner 启动Spring Boot项目时,在控制台或日志中会默认显示一个Banner,如图所示: 在我们的项目中更希望使用自己的Banner,这样看起来更帅写,但是这对于程序员来说并不 ...
- 11.Python-第三方库requests详解(三)
Response对象 使用requests方法后,会返回一个response对象,其存储了服务器响应的内容,如上实例中已经提到的 r.text.r.status_code……获取文本方式的响应体实例: ...
- Oracle中从控制文件读取的视图
Oracle中有一些数据字典视图需从控制文件中读取信息,如下所示.用户在数据库打开之前就可以访问这些视图,因为这些视图的内容存储在控制文件中. v$archived_log:归档日志信息,如大小,SC ...
- javascript动态加载js文件主流浏览器兼容版
一.代码示例: <html> <head> <meta http-equiv="Content-Type" content="text/ht ...
- JAVA_全局配置文件(配置网址,url等等)_第二种方式
@ComponentScan主要就是定义扫描的路径从中找出标识了需要装配的类自动装配到spring的bean容器中 1.application-local.yml 配置文件 2.Service 3. ...
- ES6 函数的扩展-rest参数
ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了.rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中. functio ...
- 正则表达式的lastIndex属性
js中正则表达式的使用方式有两种,一种是正则表达式对象的方法,一种是字符串对象的方法,前者有exec(str).test(str)两个方法,后者有match(regexp).replace(regex ...
- react查缺补漏01
1.描述对react理解? react是一个用于构建用户界面的JS库. react主要用于构建UI.很多人认为 React 是 MVC 中的 V(视图). react起源于:Facebook的内部项目 ...