• Ei tuloksia

Exception Handling For Fenix Messaging

3 FENIX MESSAGING TECHNIQUES

3.2 Exception Handling For Fenix Messaging

In this chapter general C++ exception handling theory is studied. In chapter 6 that the-ory is taken into use for building a robust exception handling for the Fenix Messaging concept.

In this chapter the exception handling is studied also from the developers discipline point of view. Using exception handling in software project that has many developers need rules that all the developers have to understand and obey. As a result, in chapter 6 status handling strategy for Fenix Messaging is defined.

3.2.1 C++ Exception Theory

The C++ language provides built-in support for handling anomalous situations, known as “exceptions,” which may occur during the execution of your program. The try, throw, and catch statements have been added to the C++ language to implement exception handling. With C++ exception handling, a program can communicate un-expected events to a higher execution context that is better able to recover from such abnormal events. These exceptions are handled by code which is outside the normal

36

flow of control. The Microsoft C++ compiler implements the C++ exception handling model based on the ISO WG21/ANSI X3J16 working papers towards the evolving standard for C++. [12]

According to Microsoft Developer Studio product manual [12] the program execution proceeds as follows in the presence of an exception:

1. Control reaches the try statement by normal sequential execution. The guarded section (within the try block) is executed.

2. 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 state-ment after the last catch clause following the try block in which the exception was thrown.

3. 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 con-structor 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.

4. If a matching handler is still not found, or if an exception occurs while un-winding, but before the handler gets control, the predefined run-time function termi-nate is called. If an exception occurs after throwing the exception, but before the un-wind begins, terminate is called.

5. If a matching catch handler is found, and it catches by value, its formal pa-rameter 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

37

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. [12]

3.2.2 Performance in Exception Handling

It should be clear for a developer using exceptions that they require their costs. In fact, costs can be very expensive if misused.

The costs are following. When a C++ exception is thrown, the function call chain is searched backward for a handler that can deal with the type of exception that was thrown. Of course, if no matching handler is found, the process is terminated. If a han-dler is found, the call stack is unwound, all automatic (local) variables are destroyed, and the stack is cleaned up to the context of the exception handler. Consequently, the exception overhead results from maintaining an exception handler list and a table of ac-tive automatic variables (which requires extra code, memory, and processing whether an exception is thrown or not) plus the function call chain search, automatic variable de-struction, and stack adjustment (which requires processing only when an exception is thrown.) [2]

3.2.3 C++ Exceptions and Strategy

Exceptions can help a lot in preventing bugs, but using exceptions without an estab-lished, understood strategy is just as likely to cause bugs as it is to remove them. If some team members are not throwing exceptions for errors, most likely those develop-ers are not handling exceptions either because they do not except them. The worst situa-tion is for developers not to understand excepsitua-tions in an environment that uses excep-tions. So, if exceptions are used it should be a rule for all the developers on a team to know how they are used. It would be good to have a clearly written status handling strategy available for developers.

In the book Debugging Windows Programs by Everett N. McKay and Mike Wooding [2] have been defined the following goals for a status-handling strategy:

38 1. To design the status handling

2. To determine when your program should use exceptions and when it should use