Exception handling is a programming languageA programming language is an artificial language designed to communicate instructions to a machine, particularly a computer. Programming languages can be used to create programs that control the behavior of a machine and/or to express algorithms precisely....
construct or computer hardwarePersonal computer hardware are component devices which are typically installed into or peripheral to a computer case to create a personal computer upon which system software is installed including a firmware interface such as a BIOS and an operating system which supports application software that...
mechanism designed to handle the occurrence of exceptions, special conditions that change the normal flow of programA computer program is a sequence of instructions written to perform a specified task with a computer. A computer requires programs to function, typically executing the program's instructions in a central processor. The program has an executable form that the computer can use directly to execute...
execution.
Programming languages differ considerably in their support for exception handling (as distinct from error checking, which is normal program flow that codes for responses to contingencies such as unsuccessful termination of invoked operations). In some programming languages there are functions which cannot be safely called on invalid input data or functions which return values which cannot be distinguished from exceptions. For example, in CC is a general-purpose computer programming language developed between 1969 and 1973 by Dennis Ritchie at the Bell Telephone Laboratories for use with the Unix operating system....
the {{C-lang (ASCIIThe American Standard Code for Information Interchange is a character-encoding scheme based on the ordering of the English alphabet. ASCII codes represent text in computers, communications equipment, and other devices that use text...
to integerThe integers are formed by the natural numbers together with the negatives of the non-zero natural numbers .They are known as Positive and Negative Integers respectively...
conversion) function may return 0 (zero) for any input that cannot be parsed into a valid value. In such languages, the programmer must either perform error checking (possibly through some auxiliary global variable such as C's {{C-lang) or input validation (perhaps using regular expressionIn computing, a regular expression provides a concise and flexible means for "matching" strings of text, such as particular characters, words, or patterns of characters. Abbreviations for "regular expression" include "regex" and "regexp"...
s) or both.
The degree to which such explicit validation and error checking is necessary is in contrast to exception handling support provided by any given programming environment. Hardware exception handling differs somewhat from the support provided by software tools, but similar concepts and terminology are prevalent.
In general, an exception is handled (resolved) by saving the current state of execution in a predefined place and switching the execution to a specific subroutineIn computer science, a subroutine is a portion of code within a larger program that performs a specific task and is relatively independent of the remaining code....
known as an exception handler. Depending on the situation, the handler may later resume the execution at the original location using the saved information. For example, a page faultA page fault is a trap to the software raised by the hardware when a program accesses a page that is mapped in the virtual address space, but not loaded in physical memory. In the typical case the operating system tries to handle the page fault by making the required page accessible at a location...
will usually allow the program to be resumed, while a division by zeroIn mathematics, division by zero is division where the divisor is zero. Such a division can be formally expressed as a / 0 where a is the dividend . Whether this expression can be assigned a well-defined value depends upon the mathematical setting...
might not be resolvable transparently.
From the processing point of view, hardware interruptIn computing, an interrupt is an asynchronous signal indicating the need for attention or a synchronous event in software indicating the need for a change in execution....
s are similar to resume-able exceptions, though they are typically unrelated to the user's program flow.
From the point of view of the author of a routineRoutine may refer to:*Subroutine in computer science*Choreographed routine, orchestrated dance involving several performers*Comedy routine, comedic act or part of an act*Visual routine, visual cognitive means of extracting information from a scene...
, raising an exception is a useful way to signal that a routine could not execute normally. For example, when an input argument is invalid (e.g. a zero denominator in division) or when a resource it relies on is unavailable (like a missing file, or a hard disk error). In systems without exceptions, routines would need to return some special error codeIn computer programming, error codes are enumerated messages that correspond to faults in a specific software application. They are typically used to identify faulty hardware, software, or incorrect user input in programming languages that lack exception handling, although they are sometimes also...
. However, this is sometimes complicated by the semipredicate problemIn computer programming, a semipredicate problem occurs when a subroutine intended to return a useful value can fail, but the signalling of failure uses an otherwise valid return value. The problem is that the caller of the subroutine cannot tell what the result means in this case.- Example :The...
, in which users of the routine need to write extra code to distinguish normal return values from erroneous ones.
One mechanism for raising an exception is known as a throw. The exception is said to be thrown. Execution is transferred to a "catch".
In runtime engine environments such as JavaJava is a programming language originally developed by James Gosling at Sun Microsystems and released in 1995 as a core component of Sun Microsystems' Java platform. The language derives much of its syntax from C and C++ but has a simpler object model and fewer low-level facilities...
or .NETThe .NET Framework is a software framework that runs primarily on Microsoft Windows. It includes a large library and supports several programming languages which allows language interoperability...
, there exist tools that attach to the runtime engine and every time that an exception of interest occurs, they record debugging information that existed in memory at the time the exception was thrown (call stackIn computer science, a call stack is a stack data structure that stores information about the active subroutines of a computer program. This kind of stack is also known as an execution stack, control stack, run-time stack, or machine stack, and is often shortened to just "the stack"...
and heapHeap may refer to:Computer science* Heap , a data structure commonly used to implement a priority queue* Heap , an area of memory used for dynamic memory allocationMathematics...
values). These tools are called automated exception handlingAutomated exception handling is a computing term referring to the computerized handling of errors. Runtime engines such as those for the Java language or Microsoft .Net lend themselves to an automated mode of exception or error handling. In these environments software errors do not 'crash' the...
or error interception tools and provide 'root-cause' information for exceptions.
Contemporary applications face many design challenges when considering exception handling strategies. Particularly in modern enterprise level applications, exceptions must often cross process boundaries and machine boundaries. Part of designing a solid exception handling strategy is recognizing when a process has failed to the point where it cannot be economically handled by the software portion of the process.
Exception safety
A piece of code is said to be exception-safe, if run-time failures within the code will not produce ill effects, such as memory leakA memory leak, in computer science , occurs when a computer program consumes memory but is unable to release it back to the operating system. In object-oriented programming, a memory leak happens when an object is stored in memory but cannot be accessed by the running code...
s, garbled stored data, or invalid output. Exception-safe code must satisfy invariantIn computer science, a predicate is called an invariant to a sequence of operations provided that: if the predicate is true before starting the sequence, then it is true at the end of the sequence.-Use:...
s placed on the code, even if exceptions occur. There are several levels of exception safety:
- Failure transparency, also known as the no throw guarantee: Operations are guaranteed to succeed and satisfy all requirements even in presence of exceptional situations. If an exception occurs, it will not throw the exception further up. (Best level of exception safety.)
- Commit or rollback semantics, also known as strong exception safety or no-change guarantee: Operations can fail, but failed operations are guaranteed to have no side effects so all data retain original values.
- Basic exception safety: Partial execution of failed operations can cause side effects, but invariants on the state are preserved. Any stored data will contain valid values even, if data has different values now from before the exception.
- Minimal exception safety also known as no-leak guarantee: Partial execution of failed operations may store invalid data, but will not cause a crash, and no resources get leaked.
- No exception safety: No guarantees are made (Worst level of exception safety).
For instance, consider a smart vector type, such as C++'s {{Cpp|std::vector}} or Java's {{Cpp|ArrayList}}. When an item {{Cpp|x}} is added to a vector {{Cpp|v}}, the vector must actually add {{Cpp|x}} to the internal list of objects and also update a count field that says how many objects are in {{Cpp|v}}. It may also need to allocate new memory if the existing capacity isn't large enough. This memory allocation may fail and throw an exception. Because of this, a vector that provides failure transparency would be very difficult or impossible to write. However, the vector may be able to offer the strong exception guarantee fairly easily; in this case, either the insertion of {{Cpp|x}} into {{Cpp|v}} will succeed, or {{Cpp|v}} will remain unchanged. If the vector provides only the basic exception safety guarantee, if the insertion fails, {{Cpp|v}} may or may not contain {{Cpp|x}}, but at least it will be in a consistent state. However, if the vector makes only the minimal guarantee, it's possible that the vector may be invalid. For instance, perhaps the size field of {{Cpp|v}} was incremented, but {{Cpp|x}} wasn't actually inserted, making the state inconsistent. Of course, with no guarantee, the program may crash; perhaps the vector needed to expand, but couldn't allocate the memory and blindly ploughs ahead as if the allocation succeeded, touching memory at an invalid address.
Usually at least basic exception safety is required. Failure transparency is difficult to implement, and is usually not possible in libraries where complete knowledge of the application is not available.
Verification of exception handling
The point of exception handling routines is to ensure that the code can handle error conditions. In order to establish that exception handling routines are sufficiently robust, it is necessary to present the code with a wide spectrum of invalid or unexpected inputs, such as can be created via software fault injectionIn software testing, fault injection is a technique for improving the coverage of a test by introducing faults to test code paths, in particular error handling code paths, that might otherwise rarely be followed. It is often used with stress testing and is widely considered to be an important part...
and mutation testing (which is also sometimes referred to as fuzz testingFuzz testing or fuzzing is a software testing technique, often automated or semi-automated, that involves providing invalid, unexpected, or random data to the inputs of a computer program. The program is then monitored for exceptions such as crashes or failing built-in code assertions...
). One of the most difficult types of software for which to write exception handling routines is protocol software, since a robust protocol implementation must be prepared to receive input that does not comply with the relevant specification(s).
In order to ensure that meaningful regression analysis can be conducted throughout a software development lifecycle processA software development process, also known as a software development life cycle , is a structure imposed on the development of a software product. Similar terms include software life cycle and software process. It is often considered a subset of systems development life cycle...
, any exception handling verification should be highly automated, and the test cases must be generated in a scientific, repeatable fashion. Several commercially available systems exist that perform such testing.
Exception support in programming languages
{{See also|Exception handling syntax}}
Many computer languages, such as ActionscriptActionScript is an object-oriented language originally developed by Macromedia Inc. . It is a dialect of ECMAScript , and is used primarily for the development of websites and software targeting the Adobe Flash Player platform, used on Web pages in the form of...
, Ada, BlitzMax, C++C++ is a statically typed, free-form, multi-paradigm, compiled, general-purpose programming language. It is regarded as an intermediate-level language, as it comprises a combination of both high-level and low-level language features. It was developed by Bjarne Stroustrup starting in 1979 at Bell...
, C#, D, ECMAScriptECMAScript is the scripting language standardized by Ecma International in the ECMA-262 specification and ISO/IEC 16262. The language is widely used for client-side scripting on the web, in the form of several well-known dialects such as JavaScript, JScript, and ActionScript.- History :JavaScript...
, EiffelEiffel is an ISO-standardized, object-oriented programming language designed by Bertrand Meyer and Eiffel Software. The design of the language is closely connected with the Eiffel programming method...
, JavaJava is a programming language originally developed by James Gosling at Sun Microsystems and released in 1995 as a core component of Sun Microsystems' Java platform. The language derives much of its syntax from C and C++ but has a simpler object model and fewer low-level facilities...
, MLML is a general-purpose functional programming language developed by Robin Milner and others in the early 1970s at the University of Edinburgh, whose syntax is inspired by ISWIM...
, Object PascalObject Pascal refers to a branch of object-oriented derivatives of Pascal, mostly known as the primary programming language of Embarcadero Delphi.-Early history at Apple:...
(e.g. Delphi, Free PascalFree Pascal Compiler is a free Pascal and Object Pascal compiler.In addition to its own Object Pascal dialect, Free Pascal supports, to varying degrees, the dialects of several other compilers, including those of Turbo Pascal, Delphi, and some historical Macintosh compilers...
, and the like), Objective-CObjective-C is a reflective, object-oriented programming language that adds Smalltalk-style messaging to the C programming language.Today, it is used primarily on Apple's Mac OS X and iOS: two environments derived from the OpenStep standard, though not compliant with it...
, Ocaml, PHPPHP is a general-purpose server-side scripting language originally designed for web development to produce dynamic web pages. For this purpose, PHP code is embedded into the HTML source document and interpreted by a web server with a PHP processor module, which generates the web page document...
(as of version 5), PL/1, PrologProlog is a general purpose logic programming language associated with artificial intelligence and computational linguistics.Prolog has its roots in first-order logic, a formal logic, and unlike many other programming languages, Prolog is declarative: the program logic is expressed in terms of...
, PythonPython is a general-purpose, high-level programming language whose design philosophy emphasizes code readability. Python claims to "[combine] remarkable power with very clear syntax", and its standard library is large and comprehensive...
, REALbasicRealbasic is the object-oriented dialect of the BASIC programming language used in Real Studio, a programming environment, developed and commercially marketed by Real Software, Inc of Austin, Texas for Mac OS X, Microsoft Windows, 32-bit x86 Linux and the web.- Language features :RB is a strongly...
, RubyRuby is a dynamic, reflective, general-purpose object-oriented programming language that combines syntax inspired by Perl with Smalltalk-like features. Ruby originated in Japan during the mid-1990s and was first developed and designed by Yukihiro "Matz" Matsumoto...
, Visual PrologVisual Prolog, also formerly known as PDC Prolog and Turbo Prolog, is a strongly typed object-oriented extension of Prolog. As Turbo Prolog it was marketed by Borland, but it is now developed and marketed by the Danish firm Prolog Development Center that originally developed it...
and most .NETThe .NET Framework is a software framework that runs primarily on Microsoft Windows. It includes a large library and supports several programming languages which allows language interoperability...
languages have built-in support for exceptions and exception handling. In those languages, the event of an exception (more precisely, an exception handled by the language) searches back through the stackIn computer science, a call stack is a stack data structure that stores information about the active subroutines of a computer program. This kind of stack is also known as an execution stack, control stack, run-time stack, or machine stack, and is often shortened to just "the stack"...
of function calls until an exception handler is found, with some languages calling for unwinding the stack as the search progresses. That is, if function f contains a handler H for exception E, calls function g, which in turn calls function h, and an exception E occurs in h, then functions h and g may be terminated, and H in f will handle E. An exception-handling language for which this is not true is Common LispCommon Lisp, commonly abbreviated CL, is a dialect of the Lisp programming language, published in ANSI standard document ANSI INCITS 226-1994 , . From the ANSI Common Lisp standard the Common Lisp HyperSpec has been derived for use with web browsers...
with its Condition System. Common Lisp calls the exception handler and does not unwind the stack. This allows to continue the computation at exactly the same place where the error occurred (for example when a previously missing file is now available). Mythryl's stackless implementation supports constant-time exception handling without stack unwinding.
Excluding minor syntactic differences, there are only a couple of exception handling styles in use. In the most popular style, an exception is initiated by a special statement (throw, or raise) with an exception object (e.g. with Java or Object Pascal) or a value of a special extendable enumerated type (e.g. with Ada). The scope for exception handlers starts with a marker clause (try, or the language's block starter such as begin) and ends in the start of the first handler clause (catch, except, rescue). Several handler clauses can follow, and each can specify which exception types it handles and what name it uses for the exception object.
A few languages also permit a clause (else) that is used in case no exception occurred before the end of the handler's scope was reached. More common is a related clause (finally, or ensure), that is executed whether an exception occurred or not, typically to release resources acquired within the body of the exception-handling block. Notably, C++ does not need and does not provide this construct, and the Resource-Acquisition-Is-InitializationResource Acquisition Is Initialization is a programming idiom used in several object-oriented languages like C++, D and Ada. The technique was invented by Bjarne Stroustrup to deal with resource deallocation in C++...
technique should be used to free such resources instead.
In its whole, exception handling code might look like this (in JavaJava is a programming language originally developed by James Gosling at Sun Microsystems and released in 1995 as a core component of Sun Microsystems' Java platform. The language derives much of its syntax from C and C++ but has a simpler object model and fewer low-level facilities...
-like pseudocodeIn computer science and numerical computation, pseudocode is a compact and informal high-level description of the operating principle of a computer program or other algorithm. It uses the structural conventions of a programming language, but is intended for human reading rather than machine reading...
; note that an exception type called EmptyLineException would need to be declared somewhere):
try {
line = console.readLine;
if (line.length 0) {
throw new EmptyLineException("The line read from console was empty!");
}
console.printLine("Hello %s!" % line);
console.printLine("The program ran successfully");
} catch (EmptyLineException e) {
console.printLine("Hello!");
} catch (Exception e) {
console.printLine("Error: " + e.message);
} finally {
console.printLine("The program terminates now");
}
As a minor variation, some languages use a single handler clause, which deals with the class of the exception internally.
C supports various means of error checking, but generally is not considered to support "exception handling." Perl has optional support for structured exception handling.
The C++ derivative Embedded C++Embedded C++ is a dialect of the C++ programming language for embedded systems. It was defined by an industry group led by major Japanese central processing unit manufacturers, including NEC, Hitachi, Fujitsu, and Toshiba, to address the shortcomings of C++ for embedded applications...
excludes exception handling support as it can substantially increase the size of the object code.
By contrast PythonPython is a general-purpose, high-level programming language whose design philosophy emphasizes code readability. Python claims to "[combine] remarkable power with very clear syntax", and its standard library is large and comprehensive...
's support for exception handling is pervasive and consistent. It's difficult to write a robust Python program without using its {{Python|try}} and {{Python|except}} keywords.
Exception handling implementation
The implementation of exception handling typically involves a fair amount of support from both a code generator and the runtime system accompanying a compiler. (It was the addition of exception handling to C++ that ended the useful lifetime of the original C++ compiler, CfrontCfront was the original compiler for C++ from around 1983, which converted C++ to C; developed by Bjarne Stroustrup. The preprocessor did not understand all of the language and much of the code was written via translations. Cfront had a complete parser, built symbol tables, and built a tree for...
. ) Two schemes are most common. The first, dynamic registration, generates code that continually updates structures about the program state in terms of exception handling. Typically, this adds a new element to the stack frame layoutIn computer science, a call stack is a stack data structure that stores information about the active subroutines of a computer program. This kind of stack is also known as an execution stack, control stack, run-time stack, or machine stack, and is often shortened to just "the stack"...
that knows what handlers are available for the function or method associated with that frame; if an exception is thrown, a pointer in the layout directs the runtime to the appropriate handler code. This approach is compact in terms of space, but adds execution overhead on frame entry and exit. It was commonly used in many Ada implementations, for example, where complex generation and runtime support was already needed for many other language features. Dynamic registration, being fairly straightforward to define, is amenable to proof of correctness.
The second scheme, and the one implemented in many production-quality C++ compilers, is a table-driven approach. This creates static tables at compile and link time that relate ranges of the program counterThe program counter , commonly called the instruction pointer in Intel x86 microprocessors, and sometimes called the instruction address register, or just part of the instruction sequencer in some computers, is a processor register that indicates where the computer is in its instruction sequence...
to the program state with respect to exception handling. Then, if an exception is thrown, the runtime system looks up the current instruction location in the tables and determines what handlers are in play and what needs to be done. This approach minimizes executive overhead for the case where an exception is not thrown, albeit at the cost of some space, although said space can be allocated into read-only, special-purpose data sections that are not loaded or relocated until and
unless an exception is thrown. This second approach is also superior in terms of achieving thread safety.
Other definitional and implementation schemes have been proposed as well. For languages that support metaprogrammingMetaprogramming is the writing of computer programs that write or manipulate other programs as their data, or that do part of the work at compile time that would otherwise be done at runtime...
, approaches that involve no overhead at all have been advanced.
Exception handling based on Design by Contract
A different view of exceptions is based on the principles of Design by ContractDesign by contract , also known as programming by contract and design-by-contract programming, is an approach to designing computer software...
and is supported in particular by the Eiffel languageEiffel is an ISO-standardized, object-oriented programming language designed by Bertrand Meyer and Eiffel Software. The design of the language is closely connected with the Eiffel programming method...
. The idea is to provide a more rigorous basis for exception handling by defining precisely what is "normal" and "abnormal" behavior. Specifically, the approach is based on two concepts:
- Failure: the inability of an operation to fulfill its contract. For example an addition may produce an arithmetic overflow (it does not fulfill its contract of computing a good approximation to the mathematical sum); or a routine may fail to meet its postcondition.
- Exception: an abnormal event occurring during the execution of a routine (that routine is the "recipient" of the exception) during its execution. Such an abnormal event results from the failure of an operation called by the routine.
The "Safe Exception Handling principle" as introduced by Bertrand Meyer in Object-Oriented Software ConstructionObject-Oriented Software Construction is a book by Bertrand Meyer, widely considered a foundational text of object-oriented programming. The first edition was published in 1988; the second, extensively revised and expanded edition , in 1997...
then holds that there are only two meaningful ways a routine can react when an exception occurs:
- Failure, or "organized panic": the routine fails, triggering an exception in its caller (so that the abnormal event is not ignored!), after fixing the object's state by re-establishing the invariant (the "organized" part).
- Retry: try the algorithm again, usually after changing some values so that the next attempt will have a better chance to succeed.
Here is an example expressed in Eiffel syntax. It assumes that a routine {{Eiffel|send_fast}} is normally the better way to send a message, but it may fail, triggering an exception; if so, the algorithm next uses {{Eiffel|send_slow}}, which will fail less often. If {{Eiffel|send_slow}} fails, the routine send as a whole should fail, causing the caller to get an exception.
send (m: MESSAGE) is
-- Send m through fast link, if possible, otherwise through slow link.
local
tried_fast, tried_slow: BOOLEAN
do
if tried_fast then
tried_slow := True
send_slow (m)
else
tried_fast := True
send_fast (m)
end
rescue
if not tried_slow then
retry
end
end
The boolean local variables are initialized to False at the start. If {{Eiffel|send_fast}} fails, the body ({{Eiffel|do}} clause) will be executed again, causing execution of {{Eiffel|send_slow}}. If this execution of {{Eiffel|send_slow}} fails, the {{Eiffel|rescue}} clause will execute to the end with no {{Eiffel|retry}} (no {{Eiffel|else}} clause in the final {{Eiffel|if}}), causing the routine execution as a whole to fail.
This approach has the merit of defining clearly what a "normal" and "abnormal" cases are: an abnormal case, causing an exception, is one in which the routine is unable to fulfill its contract.
It defines a clear distribution of roles: the {{Eiffel|do}} clause (normal body) is in charge of achieving, or attempting to achieve, the routine's contract; the {{Eiffel|rescue}} clause is in charge of reestablishing the context and restarting the process, if this has a chance of succeeding, but not of performing any actual computation.
Checked exceptions
The designers of Java devised checked exceptions, which are a special set of exceptions. The checked exceptions that a method may raise are part of the method's signature. For instance, if a method might throw an {{Java|IOException}}, it must declare this fact explicitly in its method signature. Failure to do so raises a compile-time error.
This is related to exception checkers that exist at least for OCaml. The external tool for OCaml is both invisible (i.e. it does not require any syntactic annotations) and facultative (i.e. it is possible to compile and run a program without having checked the exceptions, although this is not suggested for production code).
The CLU programming languageCLU is a programming language created at MIT by Barbara Liskov and her students between 1974 and 1975. It was notable for its use of constructors for abstract data types that included the code that operated on them, a key step in the direction of object-oriented programming...
had a feature with the interface closer to what Java has introduced later. A function could raise only exceptions listed in its type, but any leaking exceptions from called functions would automatically be turned into the sole runtime exception, {{CLU|failure}}, instead of resulting in compile-time error. Later, Modula-3In computer science, Modula-3 is a programming language conceived as a successor to an upgraded version of Modula-2 known as Modula-2+. While it has been influential in research circles it has not been adopted widely in industry...
had a similar feature. These features don't include the compile time checking which is central in the concept of checked exceptions, and hasn't (as of 2006) been incorporated into major programming languages other than Java.
The C++ programming language introduces an optional mechanism for checked exceptions, called exception specifications. By default any function can throw any exception, but this can be limited by a {{Cpp|throw}} clause added to the function signature, that specifies which exceptions the function may throw. Exception specifications are not enforced at compile-time. Violations result in the global function {{Cpp|std::unexpected}} being called. An empty exception specification may be given, which indicates that the function will throw no exception. This was not made the default when exception handling was added to the language because it would require too much modification of existing code, would impede interaction with code written in another language, and would tempt programmers into writing too many handlers at the local level. Explicit use of empty exception specifications can, however, allow C++ compilers to perform significant code and stack layout optimizations that normally have to be suppressed when exception handling may take place in a function. Some analysts view the proper use of exception specifications in C++ as difficult to achieve. In the upcoming C++ language standard (C++11), the use of exception specifications as specified in the current version of the standard (C++03), is deprecatedIn the process of authoring computer software, its standards or documentation, deprecation is a status applied to software features to indicate that they should be avoided, typically because they have been superseded...
.{{fact|date=October 2011}}
In contrast to Java, languages like C# do not enforce that exceptions have to be caught. Not distinguishing between to-be-called (checked) exceptions and not-to-be-called (unchecked) exceptions makes the written program more convenient, but less robust, as an uncaught exception results in an abort with a stack traceA stack trace is a report of the active stack frames at a certain point in time during the execution of a program.It is commonly used during interactive and post-mortem debugging...
.
Views on usage
Checked exceptions can, at compile timeIn computer science, compile time refers to either the operations performed by a compiler , programming language requirements that must be met by source code for it to be successfully compiled , or properties of the program that can be reasoned about at compile time.The operations performed at...
, reduce the incidence of unhandled exceptions surfacing at runtime in a given application; the unchecked exceptions ({{C++|RuntimeException}}s and {{C++|Error}}s) remain unhandled. {{Citation needed|date=August 2007}}
However, checked exceptions can either require extensive {{C++|throws}} declarations, revealing implementation details and reducing encapsulation, or encourage coding poorly-considered {{C++|try/catch}} blocks that can hide legitimate exceptions from their appropriate handlers.{{Citation needed|date=February 2010}} Consider a growing codebaseThe term codebase, or code base, is used in software development to mean the whole collection of source code used to build a particular application or component. Typically, the codebase includes only human-written source code files, and not, e.g., source code files generated by other tools or...
over time. An interface may be declared to throw exceptions X & Y. In a later version of the code, if one wants to throw exception Z, it would make the new code incompatible with the earlier uses. Furthermore, with the adapter patternIn computer programming, the adapter pattern is a design pattern that translates one interface for a class into a compatible interface...
, where one body of code declares an interface that is then implemented by a different body of code so that code can be plugged in and called by the first, the adapter code may have a rich set of exceptions to describe problems, but is forced to use the exception types declared in the interface.
It is true that {{Java|throws}} declarations like in Java reveal implementation details. Making it more convenient, allowing an exception call without this declaration reduces robustness of the code.
It is possible to reduce the number of declared exceptions by either declaring a superclass of all potentially thrown exceptions or by defining and declaring exception types that are suitable for the level of abstraction of the called method, and mapping lower level exceptions to these types, preferably wrapped using the exception chainingException chaining, or exception wrapping, is an object-oriented programming technique of handling exceptions by re-throwing a caught exception after wrapping it inside a new exception. The original exception is saved as a property of the new exception...
in order to preserve the root cause. In addition, it's very possible that in the example above of the changing interface that the calling code would need to be modified as well, since in some sense the exceptions a method may throw are part of the method's implicit interface anyway.
Using a minimal {{C++|throws Exception}} declaration or {{C++|catch (Exception e)}} is sufficient for satisfying the checking in Java. While this may have some use, it essentially circumvents the checked exception mechanism, being a coding choice discouraged by professional Java code designers.
Unchecked exception types should not be handled except, with consideration, at the outermost levels of scope. These often represent scenarios that do not allow for recovery: {{C++|RuntimeException}}s frequently reflect programming defects, and {{C++|Error}}s generally represent unrecoverable JVM failures. The view is that, even in a language that supports checked exceptions, there are cases where the use of checked exceptions is not appropriate.
Exception synchronicity
Somewhat related with the concept of checked exceptions is exception synchronicity. Synchronous exceptions happen at a specific program statement whereas asynchronous exceptions can raise practically anywhere. It follows that asynchronous exception handling can't be required by the compiler. They are also difficult to program with. Examples of naturally asynchronous events include pressing Ctrl-CControl-C is a common computer command. It is generated by pressing the key while holding down the key on a computer keyboard.In graphical user interface environments that use the control key to control the active program, control-C is often used to copy highlighted text to the clipboard...
to interrupt a program, and receiving a signalA signal is a limited form of inter-process communication used in Unix, Unix-like, and other POSIX-compliant operating systems. Essentially it is an asynchronous notification sent to a process in order to notify it of an event that occurred. When a signal is sent to a process, the operating system...
such as "stop" or "suspend" from another thread of executionIn computer science, a thread of execution is the smallest unit of processing that can be scheduled by an operating system. The implementation of threads and processes differs from one operating system to another, but in most cases, a thread is contained inside a process...
.
Programming languages typically deal with this by limiting asynchronicity, for example Java has deprecated the use of its ThreadDeath exception that was used to allow one thread to stop another one. Instead, there can be semi-asynchronous exceptions that only raise in suitable locations of the program or synchronously.
Condition systems
Common LispCommon Lisp, commonly abbreviated CL, is a dialect of the Lisp programming language, published in ANSI standard document ANSI INCITS 226-1994 , . From the ANSI Common Lisp standard the Common Lisp HyperSpec has been derived for use with web browsers...
, DylanDylan is a multi-paradigm programming language that includes support for functional and object-oriented programming, and is dynamic and reflective while providing a programming model designed to support efficient machine code generation, including fine-grained control over dynamic and static...
and SmalltalkSmalltalk is an object-oriented, dynamically typed, reflective programming language. Smalltalk was created as the language to underpin the "new world" of computing exemplified by "human–computer symbiosis." It was designed and created in part for educational use, more so for constructionist...
have a condition system (see Common Lisp Condition System) that encompasses the aforementioned exception handling systems. In those languages or environments the advent of a condition (a "generalisation of an error" according to Kent PitmanKent M. Pitman is the President of and has been involved for many years in the design, implementation and use of Lisp and Scheme systems. He is often better known by his initials KMP.Kent Pitman is the author of the Common Lisp Condition System...
) implies a function call, and only late in the exception handler the decision to unwind the stack may be taken.
Conditions are a generalization of exceptions. When a condition arises, an appropriate condition handler is searched for and selected, in stack order, to handle the condition. Conditions that do not represent errors may safely go unhandled entirely; their only purpose may be to propagate hints or warnings toward the user.
Continuable exceptions
This is related to the so-called resumption model of exception handling, in which some exceptions are said to be continuable: it is permitted to return to the expression that signaled an exception, after having taken corrective action in the handler. The condition system is generalized thus: within the handler of a non-serious condition (a.k.a. continuable exception), it is possible to jump to predefined restart points (a.k.a. restarts) that lie between the signaling expression and the condition handler. Restarts are functions closed over some lexical environment, allowing the programmer to repair this environment before exiting the condition handler completely or unwinding the stack even partially.
Restarts separate mechanism from policy
Condition handling moreover provides a separation of mechanism from policy. Restarts provide various possible mechanisms for recovering from error, but do not select which mechanism is appropriate in a given situation. That is the province of the condition handler, which (since it is located in higher-level code) has access to a broader view.
An example: Suppose there is a library function whose purpose is to parse a single syslogSyslog is a standard for computer data logging. It allows separation of the software that generates messages from the system that stores them and the software that reports and analyzes them...
file entry. What should this function do, if the entry is malformed? There is no one right answer, because the same library could be deployed in programs for many different purposes. In an interactive log-file browser, the right thing to do might be to return the entry unparsed, so the user can see it—but in an automated log-summarizing program, the right thing to do might be to supply null values for the unreadable fields, but abort with an error, if too many entries have been malformed.
That is to say, the question can only be answered in terms of the broader goals of the program, which are not known to the general-purpose library function. Nonetheless, exiting with an error message is only rarely the right answer. So instead of simply exiting with an error, the function may establish restarts offering various ways to continue—for instance, to skip the log entry, to supply default or null values for the unreadable fields, to ask the user for the missing values, or to unwind the stack and abort processing with an error message. The restarts offered constitute the mechanisms available for recovering from error; the selection of restart by the condition handler supplies the policyA policy is typically described as a principle or rule to guide decisions and achieve rational outcome. The term is not normally used to denote what is actually done, this is normally referred to as either procedure or protocol...
.
See also
- Abrahams guarantees
Exception guarantees, also known as the Abrahams guarantees after David Abrahams, who formalized the guidelines, are a set of contractual guidelines that class library implementors and clients use when reasoning about exception safety in C++ programs....
- Continuation
In computer science and programming, a continuation is an abstract representation of the control state of a computer program. A continuation reifies the program control state, i.e...
- setjmp/longjmp
- Triple fault
A triple fault is a special kind of exception generated by the CPU when an exception occurs while the CPU is trying to invoke the double fault exception handler, which itself handles exceptions occurring while trying to invoke a regular exception handler....
- Vectored Exception Handling
Microsoft Windows OS family employs some exception handling mechanisms that are based on the operation system specifics.- Structured Exception Handling :...
(VEH)
External links
{{Data types}}
{{DEFAULTSORT:Exception Handling}}