c# - Changing an unhandled exception to a handled one in a finally block -
consider program:
using system; static class program { static void main(string[] args) { try { try { throw new a(); } { throw new b(); } } catch (b) { } console.writeline("all done!"); } } class : exception { } class b : exception { } here, exception of type a thrown there no handler. in finally block, exception of type b thrown there handler. normally, exceptions thrown in finally blocks win, it's different unhandled exceptions.
when debugging, debugger stops execution when a thrown, , not allow finally block executed.
when not debugging (running stand-alone command prompt), message shown (printed, , crash dialog) unhandled exception, after that, "all done!" printed.
when adding top-level exception handler nothing more rethrow caught exception, well: there no unexpected messages, , "all done!" printed.
i understand how happening: determination of whether exception has handler happens before finally blocks executed. desirable, , current behaviour makes sense. finally blocks should not throwing exceptions anyway.
but this other stack overflow question cites c# language specification , claims finally block required override a exception. reading specification, agree that requires:
- in current function member, each
trystatement encloses throw point examined. each statements, starting innermost try statement , ending outermost try statement, following steps evaluated:
- if
tryblock ofsencloses throw point , if s has 1 or morecatchclauses, catch clauses examined [...]- otherwise, if
tryblock orcatchblock ofsencloses throw point , ifshasfinallyblock, control transferredfinallyblock. iffinallyblock throws exception, processing of current exception terminated. otherwise, when control reaches end point offinallyblock, processing of current exception continued.- if exception handler not located in current function invocation, function invocation terminated, , 1 of following occurs:
- [...]
- if exception processing terminates function member invocations in current thread, indicating thread has no handler exception, thread terminated. impact of such termination implementation-defined.
an exception isn't considered unhandled, according reading of spec, until after function invocations have been terminated, , function invocations aren't terminated until finally handlers have executed.
am missing here, or microsoft's implementation of c# inconsistent own specification?
i think problem how .net exception handling built on top of structured exception handling has different rules throwing inside block.
when exception happens seh tries find first handler able handle exception type , starts running blocks, unwinding it, based on seh logic there no such handlers, cries unhandled exception before .net can enforce own rule.
this explains top level handler (but 1 can handle exception type a) fixing problem.
the il looks valid:
.method private hidebysig static void main(string[] args) cil managed { .entrypoint // code size 49 (0x31) .maxstack 1 il_0000: nop il_0001: nop .try { il_0002: nop .try { il_0003: nop il_0004: newobj instance void a::.ctor() il_0009: throw } // end .try { il_000a: nop il_000b: newobj instance void b::.ctor() il_0010: throw } // end handler } // end .try catch b { il_0011: pop il_0012: nop il_0013: ldstr "b" il_0018: call void [mscorlib]system.console::writeline(string) il_001d: nop il_001e: nop il_001f: leave.s il_0021 } // end handler il_0021: nop il_0022: nop il_0023: nop il_0024: ldstr "a" il_0029: call void [mscorlib]system.console::writeline(string) il_002e: nop il_002f: nop il_0030: ret } // end of method program::main mono has same problem http://ideone.com/vvopx6
Comments
Post a Comment