Try return finally

Source: Internet
Author: User

 

Try catch finally is the most commonly used exception handling process. We all know that when a try block code is executed, an exception will be caught by the catch to execute the Catch Block Code, the finally block code is executed no matter how it is. But what if we add the return statement, return and finally execution sequence to the try block?

 

Finally before return ??

If you have tried this or the finally will always be executed, you will think that finally will be executed before return. However, let's look at the example below.

JS Code:

    function testtry() {            var i = 0;            try {                i = 1;                return i;            } catch (e) {                i = 2;                return i;            } finally {                i = 3;            }        }

 

. Net code:

private Int32 TestTry()        {            Int32 i = 0;            try            {                i = 1;                return i;            }            catch            {                i = 2;                return i;            }            finally            {                i = 3;            }        }

 

Should the result be 1 or 3? If finally is before return, it should be 3, but the above two pieces of code are executed as a result: 1.

Does a function or method return a return directly, and finally is not executed at all ?? Isn't this a conflict with the role that finally will always be executed?

 

Is finally executed?

Read this Code:

    function testtry() {            var i = 0;            try {                i = 1;                return i;            } catch (e) {                i = 2;                return i;            } finally {                i = 3;                return i;            }        }

 

Because. Net does not allow adding return in finally, the. NET version of this Code is not available.

This JS Code contains a return value than the previous one. What is the result? 1 or 3?

The answer is 3. What does this mean?It indicates that, regardless of the order in which return and finally are executed, finally is definitely executed.

 

The problem arises again. Since finally must have been executed, the result of our first code should be 3 instead of 1?

Cause exposure

To reveal the secrets, we need to compile the code using the. NET code in the first code:

    18:         {00000000 55                   push        ebp 00000001 8B EC                mov         ebp,esp 00000003 57                   push        edi 00000004 56                   push        esi 00000005 53                   push        ebx 00000006 83 EC 38             sub         esp,38h 00000009 8B F1                mov         esi,ecx 0000000b 8D 7D C8             lea         edi,[ebp-38h] 0000000e B9 0B 00 00 00       mov         ecx,0Bh 00000013 33 C0                xor         eax,eax 00000015 F3 AB                rep stos    dword ptr es:[edi] 00000017 8B CE                mov         ecx,esi 00000019 33 C0                xor         eax,eax 0000001b 89 45 E4             mov         dword ptr [ebp-1Ch],eax 0000001e 89 4D C4             mov         dword ptr [ebp-3Ch],ecx 00000021 83 3D 10 29 DD 03 00 cmp         dword ptr ds:[03DD2910h],0 00000028 74 05                je          0000002F 0000002a E8 E8 52 DE 6A       call        6ADE5317 0000002f 33 D2                xor         edx,edx 00000031 89 55 C0             mov         dword ptr [ebp-40h],edx 00000034 33 D2                xor         edx,edx 00000036 89 55 BC             mov         dword ptr [ebp-44h],edx 00000039 90                   nop     19:             Int32 i = 0;0000003a 33 D2                xor         edx,edx 0000003c 89 55 C0             mov         dword ptr [ebp-40h],edx     20:             try    21:             {0000003f 90                   nop     22:                 i = 1;00000040 C7 45 C0 01 00 00 00 mov         dword ptr [ebp-40h],1     23:                 return i;00000047 8B 45 C0             mov         eax,dword ptr [ebp-40h] 0000004a 89 45 BC             mov         dword ptr [ebp-44h],eax 0000004d 90                   nop 0000004e C7 45 E0 00 00 00 00 mov         dword ptr [ebp-20h],0 00000055 C7 45 E4 FC 00 00 00 mov         dword ptr [ebp-1Ch],0FCh 0000005c 68 8D 18 E5 03       push        3E5188Dh 00000061 EB 29                jmp         0000008C     24:             }    25:             catch00000063 90                   nop     26:             {00000064 90                   nop     27:                 i = 2;00000065 C7 45 C0 02 00 00 00 mov         dword ptr [ebp-40h],2     28:                 return i;0000006c 8B 45 C0             mov         eax,dword ptr [ebp-40h] 0000006f 89 45 BC             mov         dword ptr [ebp-44h],eax 00000072 E8 61 0A B3 6A       call        6AB30AD8 00000077 C7 45 E0 00 00 00 00 mov         dword ptr [ebp-20h],0 0000007e C7 45 E4 FC 00 00 00 mov         dword ptr [ebp-1Ch],0FCh 00000085 68 84 18 E5 03       push        3E51884h 0000008a EB 00                jmp         0000008C     29:             }    30:             finally    31:             {0000008c 90                   nop     32:                 i = 3;0000008d C7 45 C0 03 00 00 00 mov         dword ptr [ebp-40h],3     33:             }00000094 90                   nop 00000095 58                   pop         eax 00000096 FF E0                jmp         eax 00000098 90                   nop     34:         }00000099 8B 45 BC             mov         eax,dword ptr [ebp-44h] 0000009c 8D 65 F4             lea         esp,[ebp-0Ch] 0000009f 5B                   pop         ebx 000000a0 5E                   pop         esi 000000a1 5F                   pop         edi 000000a2 5D                   pop         ebp 000000a3 C3                   ret 000000a4 C7 45 E4 00 00 00 00 mov         dword ptr [ebp-1Ch],0 000000ab EB EB                jmp         00000098 000000ad C7 45 E4 00 00 00 00 mov         dword ptr [ebp-1Ch],0 000000b4 EB E2                jmp         00000098 

 

This is actually the real path of. Net execution.

1. The first one we can see is the RET command of the last 5th rows. This is the return command, that is, our return is not actually the actual method exit position.

2. Check the Il of return I ;.

00000047 8B 45 C0             mov         eax,dword ptr [ebp-40h] 0000004a 89 45 BC             mov         dword ptr [ebp-44h],eax 0000004d 90                   nop 0000004e C7 45 E0 00 00 00 00 mov         dword ptr [ebp-20h],0 00000055 C7 45 E4 FC 00 00 00 mov         dword ptr [ebp-1Ch],0FCh 0000005c 68 8D 18 E5 03       push        3E5188Dh 00000061 EB 29                jmp         0000008C 

 

In addition to some mov operations, the method execution is not aborted. The last sentence is the JMP jump command, and the jump address is exactly the starting address of the Finally block, that is, finally is executed after this sentence is executed.

3. Before analyzing the return I Il, let's take a look at the two sections of the C # code with no specific correspondence at the beginning and end of the method, they are the "Opening" prologue code: Responsible for initializing the method before the method starts. The most important thing is to allocate memory for the local variables of the method on the thread stack, and allocate memory for the return value, from the code you can see that the two addresses are allocated and initialized [ebp-40h] [ebp-44h]; end code epilogue code: method to complete cleaning and return to the caller.

4, then the last piece, we can see that each operation I value, there will be mov dword ptr [ebp-40h] such an operation, that is to say, this address stores the I value. Then we can see from the return I; Il code that it first executes two operations: the value of the [ebp-40h] To eax, and then the eax value to the [ebp-44h], that is, the return value is saved in the [ebp-44h] address.

5, to the end, just put the value of the [ebp-44h] address into the data register, finally obtained by the caller.

 

The truth is that the variables and return values are stored in two different places. When I is returned, only the I value is used to fill in the return value address. When finally, the I value is changed again, but does not affect the return value. As for JS Finally, you can return I again; or you may have modified the value of the address that returned the value.

 

What about the reference type?

For the value type, the allocated address is saved directly as a value. Modifying the I value once again does not affect the return value. For the reference type, the address is saved as a pointer. Should it be another time?

function testtry2() {            var o = {};            o.i = 0;            try {                o.i = 1;                return o;            } catch (e) {                o.i = 2;                return o;            } finally {                o.i = 3;            }        }

 

Boldly guess the I value of the returned object. Right, it is 3.

 

After the drill is completed.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.