Exceptional Handling In C++ In Comparision With Java
To the programmers it is very common concept that bugs are of two types i.e logical errors and syntactic errors. Poor understanding of the problem and solution procedure leads to logical errors whereas, the syntactic errors arise due to poor understanding of the language itself. We can detect these errors by using debugging and testing procedures.
We often come across some peculiar problems other than logic or syntax errors. They are known as "exceptions". Occasionally functions don’t work properly. The traditional means of reporting failure is to return some indication to the caller.An exception is defined as "a case in which a rule or principle does not apply." Exception is also defined as an objection to something. An exception is an unexpected and presumably objectionable condition that occurs during the execution of the program. Anomalies might include conditions such as division by zero, access to an array outside its bounds, or running out of memory or disk space. When a program encounters an exceptional condition, it is important that it is identified and dealt with effectively.
The exception mechanism is based on the keywords try,catch, and throw.
It works like this: A function trys to get through a piece of code. If the code detects a problem, it throws an error indication that the calling function must catch.
Exceptions are of two kinds, namely, "synchronous exception" and "asynchronous exceptions". Errors such as "out-of-range index" and "over-flow" below to synchronous type exceptions. The errors that are caused by events beyond control of the program (such as keyboard interrupts) are called asynchronous exceptions. The proposed exception handling mechanism in C++ is designed to handle only synchronous exceptions.
The purpose of the exception handling mechanism is to provide means to detect and report an "exceptional circumstance" so that appropriate action can be taken. The mechanism suggests a separate error handling code that performs the following tasks:-
main() starts out by creating a block outfitted with the try keyword. Within this block, it can proceed the way it would if the block were not present. In this case, main() attempts to calculate the factorial of a negative number. The clever factorial() function detects the bogus request and throws an error indication using the throw keyword. Control passes to the catch phrase, which immediately follows the closing brace of the try block. The second call to factorial() is not performed.
The declaration for factorial() also announces to the compiler that it may throw a string object somewhere under the right conditions. This is a relatively new, and so far optional, feature. If absent, the function may throw any object that it wants. If present, the function can throw only one of the types of objects included in the declaration.
Let us take a closer look at the steps that the code goes through to handle an exception. When the throw occurs, C++ first copies the thrown object to some neutral place. It then begins looking for the end of the current try block. If a try block is not found in the current function, control passes to the calling function. A search is then made of that function. If no try block is found there, control passes to the function that called it, and so on up the stack of calling functions. This process is called unwinding the stack.
An important feature of stack unwinding is that as each stack is unwound, objects that go out of scope are destructed just as though the function had executed a return statement. This keeps the program from losing assets or leaving objects dangling.
When the encasing try block is found, the code searches the first catch phrase immediately following the closing brace of the catch block. If the object thrown matches the type of argument specified in the catch statement, control passes to that catch phrase. If not, a check is made of the next catch phrase. If no matching catch phrases are found, the code searches for the next higher level try block in an ever-outward spiral until an appropriate catch can be found. If no catch phrase is found, the program is terminated.
Consider the following example:
The output from executing this program appears as follows:
Constructing object a
Constructing object b
Constructing object c
Constructing object d
Destructing object d
Destructing object c
Destructing object b
Destructing object a
Press any key to continue . . .
First, we see the four objects a, b, c, and d being constructed as main() calls f1() which calls f2() which calls f3(). Rather than return, however, f3() throws the integer 10. Because no try block is defined in f3(), C++ unwinds f3()'s stack, causing object d to be destructed. The next function up the chain, f2() defines a try block, but its only catch phrase is designed to handle string, which doesn't match the int thrown. Therefore, C++ continues looking. This unwinds f2()'s stack, resulting in object c being destructed.
Back in f1(), C++ finds another try block. Exiting that block causes object b to go out of scope. C++ skips the first catch phrase for a float. The next catch phrase matches the int exactly, so C++ passes control to this phrase.
Control passes from the catch(int) phrase to the closing brace of the final catch phrase and from there back to main(). The final catch (…) phrase, which would catch any object thrown, is skipped because a matching catch phrase was already found.
The thing following the throw keyword is actually an expression that creates an object of some kind. In the examples so far, I've thrown an int and a string object, but throw can handle any type of object. This means you can throw almost as much information as you want.
Consider the following update to the factorial program, CustomExceptionClass:
The output from this program appears as follows:
Factorial of 3 is 6
Error <Negative argument not allowed> - value is -1
in function factorial()
in file C:\CPP_Programs\CustomExceptionClass\main.cpp line #53
Press any key to continue . .
This program appears much the same as the factorial program given above. The difference is the use of a user-defined MyException class that contains more information concerning the nature of the error than a simple string contains. The factorial program is able to throw the error message, the illegal value, and the exact location where the error occurred. _FILE_, _LINE_ and _f unc_ are intrinsic #defines that are set to the name of the source file, the current line number in that file, and the name of the current function, respectively. The catch snags the MyException object and then uses the built-in display() member function to display the error message.
A function that allocates resources locally may need to catch an exception, do some processing and then rethrow it up the stack chain.
Consider the following example:
The memory allocated by new isn't returned to the heap automatically. If otherFunction() were to throw an exception, control would exit the program without invoking delete, and the memory allocated at the beginning of fileFunc() would be lost.
To avoid this problem, fileFunc() can include a catch (…) to catch any exception thrown:
Within this phrase, fileFunc() returns the memory it allocated earlier to the heap. However, it is not in a position to process the remainder of the exception because it has no idea what could have gone wrong. It doesn't even know what type of object it just caught.The throw keyword without any arguments rethrows the current exception object back up the chain to some function that can properly process the error.
Re: Exceptional Handling In C++ In Comparision With Java
If you liked this article do nominate this article for Article of the month - May 2010
|All times are GMT +5.5. The time now is 01:50.|