Afficher un message
Vieux 15/10/2007, 11h17   #2
Erik Wikström
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: efficient exception handling

On 2007-10-15 09:44, terminator wrote:
> I found the following as the ANSI C++ std behavior of the exception
> handling mechanism in the documentation of my compiler:
>
> Control reaches the try statement by normal sequential execution. The
> guarded section within the try block is executed.
> If no exception is thrown during execution of the guarded section, the
> catch clauses that follow the try block are not executed. Execution
> continues at the statement after the last catch clause following the
> try block in which the exception was thrown.
> If an exception is thrown during execution of the guarded section or
> in any routine the guarded section calls (either directly or
> indirectly), an exception object is created from the object created by
> the throw operand. (This implies that a copy constructor may be
> involved.) At this point, the compiler looks for a catch clause in a
> higher execution context that can handle an exception of the type
> thrown (or a catch handler that can handle any type of exception). The
> catch handlers are examined in order of their appearance following the
> try block. If no appropriate handler is found, the next dynamically
> enclosing try block is examined. This process continues until the
> outermost enclosing try block is examined.
> If a matching handler is still not found, or if an exception occurs
> while unwinding, but before the handler gets control, the predefined
> run-time function terminate is called. If an exception occurs after
> throwing the exception, but before the unwind begins, terminate is
> called.
> If a matching catch handler is found, and it catches by value, its
> formal parameter is initialized by copying the exception object. If it
> catches by reference, the parameter is initialized to refer to the
> exception object. After the formal parameter is initialized, the
> process of unwinding the stack begins. This involves the destruction
> of all automatic objects that were constructed (but not yet
> destructed) between the beginning of the try block associated with the
> catch handler and the exception's throw site. Destruction occurs in
> reverse order of construction. The catch handler is executed and the
> program resumes execution following the last handler (that is, the
> first statement or construct which is not a catch handler). Control
> can only enter a catch handler through a thrown exception, never via a
> goto statement or a case label in a switch statement.
>
> I do not feel much doubt about the standardness of the above context ,
> but IMO the std could be more elegant with the some minor
> modifications;


To my knowledge the way exceptions work in C++ is very similar to the
way they work in other languages (though I do not claim to have
knowledge of all languages that support exceptions). I would assume that
this is not because the inventors of the other languages could not
imagine other ways to do things, but rather because it is the most sane
way of doing things.

> i.It looks as if the stack unwinding is performed at 'throw'
> site .but IMHO if the stack unwinding is left to the 'catch' site the
> program will be more flexible;because it gives us the option to handle
> the trouble and resume the program from the statement after the
> throw ,rather than stopping what was performing before the
> throw.


If it was possible to handle the exception at the site where it was
thrown it should have been caught at the same place and the problem
fixed and no exception would have propagated in the first place. The
reason for an exception to be caught at another site would be because
that is to only logical place to handle the exception.

> Therefore a default exception handler also need be implicitly
> defined ,so that it can catch all exeptions and do nothing but unwind
> the stack and terminate.
> ii.Appliction of some existing keywords can be extended:
>
> 1.default:
>
> The 'default' keyword can be introduced as an acceptable parameter to
> the 'throw' statement as the uncatchable(unhandleable) exception which
> cannot be cought by any catch block except the implicitly defined
> default handler ,so that a 'throw default' performs a secure exit on
> current thread:
>
> try{
> throw default;/*unwind the stack completely ,then terminate this
> thread.*/
> }catch(...){
> //shall never be reached:cannot catch the default exception.
> }


The whole idea behind exceptions it that they can be thrown and then
caught, why would anyone want an uncatchable exception? If you want to
terminate the program there are other ways to do so, such as abort().

> 2.break:
>
> A 'break' statement inside a catch block - that does not belong to any
> loop or 'switch' statement - must break the catch block:
>
> try{
> throw "serious but not fatal";
> }catch(...){
> A ca;
> B cb;
> if(condition) break;//goto end;
> do_something();
> end:
> }/* cb.~B(); ca.~A();*/


That would be convenient, but hardly something that we can not live
without, the same thing can be accomplished using both goto (ugh!) and
the normal control statements.

> 3.continue:
>
> A 'continue' statement inside a catch block - that does not belong to
> any loop - must mean that the exception has been resolved and the
> program should resume from the first statement after the 'throw' that
> has raised or re-thrown the exception :
>
> try{
> throw "throw 1";
> keep_on1:
> do_something();
>
> }cathch(const char *){
> try{
> throw;//re-throw
> keep_on2:
> continue;/*go to keep_on1 as if every thing were ok.*/
>
> }catch(...){
> continue;/*go to keep_on2 as if no ecxeption has occured*/
> }
> }
>
> Thus if a catch block owns a 'continue' statment,the compiler should
> postpone stack unwinding to exiting from the catch block - either
> normally or via a 'break' or 'goto' to outside the catch block- rather
> than the beginning of catch block.


Consider the following, an exception is thrown in a constructor. In the
catch-block you use continue to resume the execution which means that
your code will continue to run and try to perform operations on a not
fully constructed object. Not a good idea. The reason the exception was
thrown was that correct execution was no longer possible, the only
correct way of handling this is to go back a little and then deal with
the situation (by aborting, trying again, trying something different, etc.).

--
Erik Wikström
  Réponse avec citation
 
Page generated in 0,08611 seconds with 9 queries