How is an exception transferred to find a handler?

别等时光非礼了梦想. 提交于 2019-12-02 11:06:12

问题


When an exception is thrown stack unwinding is initiated until handling code is encountered, but I am a little unclear on the mechanics of the whole process.

1 - where is the exception stored? I don't mean the actual exception object, which may be quite big, e.g. have a message string or something, but the actual reference or pointer if you will. It must be some uniform storage location so that it can survive going down as the stack is unwinding and reach a handling location?

2 - how does the program flow determine whether to it has to unwind the particular function frame and call the appropriate destructors associated with the program counter indicated location or seek exception handing before it unwinds further?

3 - how is the actual check between what is thrown and what exceptions are being couth happening?

I am aware that the answer might include platform specific stuff, in which case such will be appreciated. No need to go beyond x86/x64 and ARM though.


回答1:


These are all implementation details, to be decided during the (non-trivial) process of designing an exception handling mechanism. I can only give a sketch of how one might (or might not) choose to implement this.

If you want a detailed description of one implementation, you could read the specification for the Itanium ABI used by GCC and other popular compilers.

1 - The exception object is stored in an unspecified place, which must last until the exception has been handled. Pointers or references are passed around within the exception handling code like any other variable, before being passed to the handler (if it takes a reference) by some mechanism similar to passing a function argument.

2 - There are two common approaches: a static data structure mapping the program location to information about the stack frame; or a dynamic stack-like data structure containing information about active handlers and non-trivial stack objects that need destroying.

In the first case, on throwing it will look at that information to see if there are any local objects to destroy, and any local handlers; if not, it will find the function return address on the local stack frame and apply the same process to the calling function's stack frame until a handler is found. Once the handler is found, the CPU registers are updated to refer to that stack frame, and the program can jump to the handler's code.

In the second case it will pop entries from the stack structure, using them to tell it how to destroy stack objects, until it finds a suitable handler. Once the handler is found, and all unwound stack objects destroyed, it can use longjmp or a similar mechanism to jump to the handler.

Other approaches are possible.

3 - The exception handling code will use some kind of data structure to identify a type, allowing it to compare the type being thrown with the type for a handler. This is somewhat complicated by inheritance; the test can't be a simple comparison. I don't know the details for any particular implementation.




回答2:


Source: How do exceptions work (behind the scenes) in c++ (I read the assembly and answered the questions by what I understood)

Question 1#:

movl    $1, (%esp)
call    __cxa_allocate_exception
movl    $_ZN11MyExceptionD1Ev, 8(%esp)
movl    $_ZTI11MyException, 4(%esp)

_ZTI11MyException is the exception. It looks as if it has it's own allocation not in the stack and it places the pointer in register named eax.

Question 2#:

.LFE9:
.size   _Z20my_catching_functionv, .-_Z20my_catching_functionv
.section    .gcc_except_table,"a",@progbits
.align 4

It looks like table that is stored in static data in the program. So it can know where it can catch. There was nothing about how objects destruct themself after unwinding frames so this is from Visual Studio: (The link at the top is from Linux)

        MyClass s, s2, s3, s4;
 mov         dword ptr [ebp-4],3  
        try {
            {
                MyClass s, s2, s3, s4;
 mov         byte ptr [ebp-4],7  
            }

It looks like it saves the number of objects to destroy. For example when it finishes:

call        MyClass::~MyClass (0DC1163h)
mov         dword ptr [ebp-4],0FFFFFFFFh

0FFFFFFFFh means nothing's to destruct. If I find something about how it actually finds and destroyes them I will add here.

Question 3#:

As in the previous question, you see there's table for it, it can know whatever it's in the right function.



来源:https://stackoverflow.com/questions/26652963/how-is-an-exception-transferred-to-find-a-handler

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!