当前位置:网站首页>C++ exception implementation mechanism
C++ exception implementation mechanism
2020-11-09 23:48:00 【shzwork】
、C Function calls and returns
To understand C++ Before the exception mechanism is implemented , First of all, we should understand the call and return mechanism of a function , This involves ESP and EBP register . Let's take a look at the flow of function calls and returns .
The following is the call Convention __stdcall Call function test(int p1,int p2) Assembly code for
Suppose the stack pointer before the function is executed ESP by NN
push p2 ; Parameters 2 Push , ESP -= 4h , ESP = NN - 4h
push p1 ; Parameters 1 Push , ESP -= 4h , ESP = NN - 8h
call test ; Press in return address ESP -= 4h, ESP = NN - 0Ch
{
push ebp ; Protect the previous EBP The pointer , EBP Push , ESP-=4h, ESP = NN - 10h
mov ebp, esp ; Set up EBP The pointer points to the top of the stack NN-10h
mov eax, dword ptr [ebp+0ch] ;ebp+0ch by NN-4h, The parameter 2 The location of
mov ebx, dword ptr [ebp+08h] ;ebp+08h by NN-8h, The parameter 1 The location of
sub esp, 8 ; Space occupied by local variables ESP-=8, ESP = NN-18h
...
add esp, 8 ; Release local variables , ESP+=8, ESP = NN-10h
pop ebp ; Out of the stack , recovery EBP, ESP+=4, ESP = NN-0Ch
ret 8 ;ret return , Pop up return address ,ESP+=4, ESP=NN-08h, Add the operands after 8 To balance the stack ,ESP+=8,ESP=NN, Restore the stack before entering the function .
}
The function stack architecture mainly carries the following parts :
1、 Pass parameters : Usually , Function call parameters are always at the top of the function stack framework .
2、 Pass the return address : Tell the callee return The sentence should be return Where to go? , Usually points to the next statement of the function call ( Offset in code snippet ).
3、 Holds the current stack pointer of the caller : Easy to clean up all local variables of the callee 、 And restore the caller's scene .
4、 Store all local variables in the current function : Do you remember ? As mentioned earlier, all local and temporary variables are stored on the stack .

2、C++ Function call
First of all, make it clear , here “C++ function ” Refer to :
1、 This function may throw an exception directly or indirectly : That is, the definition of the function is stored in a C++ compile ( Not tradition C) In the unit , And this function doesn't use “throw()” Anomaly filter
2、 The definition of this function uses try block .
One of the above two can be satisfied . In order to be able to successfully catch exceptions and complete stack fallback correctly (stack unwind), The compiler must introduce some additional data structures and corresponding processing mechanisms . Let's first take a look at the stack framework with exception handling mechanism :

From the figure 2 so , At every C++ There are some more things in the stack framework of the function . Observe carefully , You'll find that , The extra thing is just one EXP Type of structure . Further analysis will reveal that , This is a typical one-way linked list structure :
piPrev The member points to the previous node in the linked list , It is mainly used to search for matching catch block , And complete the stack fallback .
piHandler Members point to the data structures necessary for exception capture and stack fallback ( It's mainly two tables with key data :“try” Block table :tblTryBlocks And “ Stack fallback table ”:tblUnwind).
nStep Members are used to locate try block , And find the right entry in the stack fallback table .
It should be noted that : The compiler will do it for every “C++ function ” Define a EHDL structure , But only for the inclusion of “try” Function definition of block tblTryBlocks member . Besides , The exception handler also maintains a pointer to the current exception handling framework for each thread . This pointer points to the end of the exception handler list , Usually stored in some place TLS A trough or place where a similar effect can be achieved .
3、 Stack back (stack unwind)
“ Stack back ” Is accompanied by the introduction of exception handling mechanism C++ A new concept in , It is mainly used to ensure that the exception is thrown 、 After capturing and processing , All objects whose lifetime has ended will be destructed correctly , The space they occupy will be recycled correctly . Let's take a look at how the compiler implements the stack fallback mechanism :

In the picture “FuncUnWind” Within the function , All real codes are shown in black and blue font , The code generated by the compiler is indicated in gray and orange fonts . here , The picture shows nStep Variables and tblUnwind The role of members is very obvious .
nStep Variables are used to track the construction of local objects within a function 、 In the stage of deconstruction . And then with the compiler generated for each function tblUnwind surface , Then we can complete the unwinding mechanism . In the table pfnDestroyer Field records the destruct operations that should be performed in the corresponding phase ( Destructor pointer );pObj Field records the corresponding object this Pointer offset . take pObj The offset value of the reference plus the current stack frame base address (EBP), That is to put in pfnDestroyer Of a destructor this The pointer , In this way, the destruct of the object is completed . and nNextIdx The field points to the row of the next object to be destructed ( Subscript ).
When an exception occurs , The exception handler first checks for... In the current function stack framework nStep value , And pass piHandler obtain tblUnwind[] surface . And then nStep Bring it into the table as a subscript , Perform the destruct operation defined by this line , And then turn from nNextIdx The next line to point to , until nNextIdx by -1 until . After the stack fallback of the current function is finished , The exception handler can follow the current function stack frame piPrev The value of is traced back to the previous node in the exception handling chain , Until all the fallback work is done .
It is worth mentioning that ,nStep The value of is completely determined at compile time , The runtime only needs to perform a few simple integer immediate assignments ( It is usually assigned directly to CPU One of the registers in ). Besides , For all internal types and using the default construct 、 destructor ( And all its members and base classes also use the default method ) The type of , Its creation and destruction do not affect nStep Value .
Be careful : If in the stack fallback process , An exception was thrown again due to a call to a destructor ( The exception in the exception ), Is considered a serious failure of the exception handling mechanism . At this point, the process will be forcibly prohibited . To prevent this , Should be used in all destructors that may throw exceptions “std::uncaught_exception()” Method to determine whether stack rollback is currently in progress ( namely : There is an exception that has not been caught or has not been fully processed ). " , You should prevent the exception from being thrown again .
4、 Exception trapping
When an exception is thrown , It will immediately trigger C++ Exception capture mechanism of :

In the last section , We have seen nStep Variable in tracking object construction 、 The role of the structure . actually nStep Besides being able to track object creation 、 Beyond the destruction stage , It can also identify whether the current execution point is in try In block , as well as ( If the current function has more than one try Block words ) Where on earth try In block . It's through every try The entrance and exit of the block are respectively nStep Give a unique ID value , And ensure nStep In the corresponding try Changes within a block are implemented within this range .
In the specific implementation of exception capture , First ,C++ The exception handler checks whether the location of the exception is in one of the current functions try Within the block . This can be done by changing the current function's nStep The values are in the order of piHandler Point to tblTryBlocks[] The range of items in the table is [nBeginStep, nEndStep) To complete .
for example : If the figure 4 Medium FuncB stay nStep == 2 There was an exception when , By comparing FuncB Of tblTryBlocks[] Table discovery 2∈[1, 3), So the anomaly occurs in FuncB The first one in try In block .
secondly , If the exception occurs at a location in the current function try block , Then try to match the tblTryBlocks[] In the corresponding entry tblCatchBlocks[] surface .tblCatchBlocks[] The table records and specifies try Block matching appears all of catch Block related information , Including this catch The type of exception and its starting address that can be captured by a block .
If you find a match catch block , Copy the current exception object here catch block , Then jump to its entry address and execute the code in the block .
otherwise , It indicates that the location of the exception is not in the current function try block , Or this try There is no... In the block that matches the current exception catch block , At this point, it goes along the function stack frame piPrev The address referred to ( namely : The last node in the exception handling chain ) Repeat the process step by step , Until we find a match catch Block or arrive at the first node of the exception handling chain . For the latter , We call an uncapped exception occurred , about C++ For exception processors , An uncapped exception is a serious error , Will cause the current process to be forced to end .
5、 Throw an exception
Let's talk about the whole thing C++ The last link in the exception handling mechanism , Throw exception :

In compiling a paragraph C++ Code , The compiler will take all throw The statement is replaced by its C++ A specified function in the runtime library , Here we call it __CxxRTThrowExp( Like all other data structures and property names mentioned in this article , In practice, it can be any name ). This function receives a compiler approved internal structure ( We call it the EXCEPTION structure ). This structure contains the starting address of the object to be thrown 、 The destructor used to destroy it , As well as its type_info Information . For not enabled RTTI Mechanism ( The compiler has disabled RTTI Mechanism or no virtual table is used in the class hierarchy ) Exception class hierarchy of , It may also contain all of its base classes type_info Information , In order to correspond with catch Block to match .
In the dark gray box in the picture , We use C++ Pseudo code shows the function FuncA Medium “throw myExp(1);” The way statements will eventually be translated by the compiler . In fact, in most cases ,__CxxRTThrowExp Function is what we mentioned many times before “ Exception handler ”, Exception capture and stack fallback and other important work is done by it .
__CxxRTThrowExp First receive ( And save )EXCEPTION object ; And then from TLS:Current ExpHdl Corresponding to the current function piHandler、nStep And other exception processing related data ; And according to the mechanism mentioned above, exception capture and stack rollback are completed . So it's done, including “ Throw out ”->“ Capture ”->“ Back off ” And so on .
6、 summary
That's all C++ The implementation principle of exception , Of course, other language exception capture mechanism is the same idea to achieve exception handling .
版权声明
本文为[shzwork]所创,转载请带上原文链接,感谢
边栏推荐
- CUDA_ Memory model
- Guest interview: Wang Jian
- sql 筛选查询重复列
- 会展云技术解读 | 面对突发事故,APP 如何做好崩溃分析与性能监控?
- C / C + + Programming Notes: C language development tank war! In memory of our lost little overlord game
- Mongodb kernel source code implementation, performance tuning, best operation and maintenance practice series command processing module source code implementation 1
- CUDA_存储器模型
- mongodb内核源码实现、性能调优、最佳运维实践系列-command命令处理模块源码实现一
- Postman(一)---功能介绍
- lvgl 库 V7版本相关应用
猜你喜欢

sql 筛选查询重复列

leetcode之最后一个单词的长度

获取List集合对象中某一列属性值

毕业设计之 ---基于微服务框架的电影院订票系统

SQL intercepts the data before and after the '.'

Centos7 operating system security hardening series (2)

The movie theater booking system based on micro Service Framework

lvgl 库 V7版本相关应用

Important components of Apache Hadoop

Make a home page
随机推荐
Formal class D25
代码中的软件工程--对menu项目的源码分析
Brief analysis of LinkedList source code
将Map中对应的key和value赋值到对象中
表单验证,为避免全局污染,少定义全局变量写法
Software engineering in code -- source code analysis of menu project
CUDA_共享内存、访存机制、访问优化
Hengxun Technology: the way to deal with server downtime
价值超10亿美元的直播系统架构图是什么样子的?
The problem of looting by leetcode
Optimization of commodity backstage system
CRM系统能帮助企业做哪些事?
DB-Engines 11月数据库排名:PostgreSQL坐稳同期涨幅榜冠军宝座
11.9
编码风格:Mvc模式下SSM环境,代码分层管理
day84:luffy:优惠活动策略&用户认证&购物车商品的勾选/结算
nodejs篇-手写koa中间件
Guest interview: Wang Jian
Common concepts and points for attention of CUDA
Algorithm template arrangement (1)
