ERROR HANDLING Aims
To enable
students to: ·
understand
various error handling techniques ·
use
function return values ·
use
exceptions Understand various
error handling techniques
Bugs can be
considered to be problems in a program that cause undesirable behaviour.
Previous notes made suggestions on how to minimise the chances of coding bugs,
such as uninitialised variables, entering a program. A related
area is the handling of error situations within a program. Errors include
invalid user response, the end of an input file, failure of system calls, etc.
Programs that can not handle such situations are bugged and liable to fail in
unexpected ways. Many C++
functions represent error conditions through the value they return after
execution. Frequently negative values indicates an error occurred, and positive
that all is well. Using this knowledge several ways of structuring code may be
followed. One
approach is to finish execution of the current function whenever an error takes
place, as in the following: int iSomefunction () { … ptrMem = new char; if (ptrMem == NULL) { return -1; } … } Although
simple to implement, such an approach presents several problems. In complicated
functions it is often very difficult to work out all conditions in which the
function will terminate, consequently future maintainers may miss certain
failure conditions. Further, large functions often consume resources, such as
files and heap space, during their execution. The developer of a function that
terminates in multiple places must ensure all resources allocated up to that
point are freed, a somewhat onerous task. It is
frequently cleaner to only have one entry and exit point for a function. In
this way it is easier for a developer to ensure all appropriate resources are
freed and a maintainer to find their way around the code. Unfortunately, this
can make the function itself appear more convoluted, asin: int iSomefunction () { … ptrMem = new char; if (ptrMem == NULL) { iErrVal =-1; } else { … } return iErrVal; } An
alternative to the introduction of an error indicator (iErrVal in the above code) is the use nested if statements. In uncomplicated
functions this can be useful, but it is very easy for your code to spread along
way across the screen. In an
attempt to simplify error handling within source code C++ has introduced
exception handling - note the Turbo C++ compiler does not fully support this
mechanism. Exceptions remove the need for explicit checking of function return
codes, instead a single block of code is placed at the end of a function and is
called by the compiler if any called functions fail. A typical piece of code
appears as: int iSomefunction () { try { … ptrMem = new char; …
return 0; } catch () { return -1; } } Use function
return values
When
generating your own return code values, do so in a consistent way. For example,
if you are using negative numbers to represent failure conditions always do
this, do not use positive values in some situations. If possible
try and reserve values for specific error conditions, for example -5 may be used to represent a file open failure, and only a
file open failure. Document
your return codes to assist in future maintenance. Functions should indicate
what values they are likely to return to their callers. Never
totally rely on the documentation of another function. To code defensively it
pays to expect functions to return other values to those specified in their
documentation. It is common for code to be modified, but the corresponding
documentation to be left untouched. Use exceptions
In order to
process an exception your code needs a catch block. These portions of code can
be written to handle exceptions from a specific class, as in: catch
(CMyObject) { … } which will
handle those raised by the CMyObject class, or generic in which case no class
name is provided in the catch statement. If an
exception is raised within a function that has no handler, then the failure is
passed down the stack of executing functions until a handler is met that can
cope with it. If none is found then the process is terminated. To raise
exceptions a program uses the throw statement, which is very similar to
return. For example, to throw and catch a
simple error message the following code may be used: try { … throw "Memory allocation
failure!"; } catch( char * str ) { cout << "Exception raised:
" << str << '\n'; } return 0; |
|
||
|
|||
|
Last updated: 11th July 2006. copyright © 2006 Greystoke Systems Ltd. Web address: http://www.gsys.biz/Documents/Services/Tuition/CityAndGuilds/FurtherWork/ErrorHandling.htm |