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
try
statement encloses throw point examined. each statements
, starting innermost try statement , ending outermost try statement, following steps evaluated:
- if
try
block ofs
encloses throw point , if s has 1 or morecatch
clauses, catch clauses examined [...]- otherwise, if
try
block orcatch
block ofs
encloses throw point , ifs
hasfinally
block, control transferredfinally
block. iffinally
block throws exception, processing of current exception terminated. otherwise, when control reaches end point offinally
block, 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