In Java, if a specific line of code causes the program to crash, then the exception is caught and the program continues to execute.
However, in C++, if I have a piece of code that causes the program to crash, like:
try
{
int x = 6;
int *p = NULL;
p = reinterpret_cast<int*>(x);
*p = 10; // the program cra开发者_如何转开发shed here
cout << "x = " << *p << endl;
}
catch(const char* Message)
{
cout << "There is an run-time error";
}
Then the program still crash and the exception is not caught.
So what is the point of exception handling in C++? Am I misunderstanding something?
The line that crashes is dereferencing an invalid pointer. In C++ this will not throw an exception. Instead it is undefined behaviour.
There's no such thing as a null pointer exception in C++, unlike Java which will throw a null pointer exception. Instead dereferencing an invalid pointer will lead to undefined behaviour. Undefined behaviour does not always imply a crash, however if it crashes you're lucky.
Language overview:
Finally and RAII
One of the most significant differences between C++ and Java is that Java supports a finally
statement. Code in the finally
block is always run regardless of whether code in the preceding catch
block is executed or not. For example:
try
{
}
catch (SomeException e)
{
}
finally
{
//code here is always exectued.
}
The purpose of the finally statement is to allow the programmer cleanup at that point, i.e. release sockets, close file handles etc... Even though Java runs a garbage collector, garbage collection only applies to memory and no other resource. There are still occasions where you have to manually dispose of resources. Now C++ doesn't have a finally
statement so users of the language are advised to adhere to the RAII principle (Resouce Acquisition is Initialization) Stroustrup has an explanation about it here: http://www.stroustrup.com/bs_faq2.html#finally. I prefer to call it Resource destruction is deallocation
but basically when your object falls out of scope, invoking the destructor, then that destructor should release whatever resources the object maintained.
For example, C++11x provides a std::unique_ptr to manage this:
void foo()
{
std::unique_ptr<T> t(new T)
try
{
//code that uses t
}
catch (...)
{
}
}
The resource allocated via new
will be deleted when the function ends.
catch all statements
Because all exceptions in Java inherit from a common base class Exception
if you want your catch clause to catch any exception, then set it up like this:
catch (Exception e)
{
//any exception thrown will land here.
}
In C++ there's no restriction on what can be thrown and no common base class for all exceptions. Standard practice is to form your custom exception class by inheriting from std::exception but the language doesn't enforce this. Instead there's a special syntax for catching all exceptions:
catch (...)
{
}
Unhandled exceptions
This is another area where the languages behave differently. In C++ a thrown exception that is not caught will call std::terminate. std::terminate's default behaviour is to call abort which generates a SIGABRT and the entire program stops.
In Java the behaviour is to print a stack trace and terminate the thread that the uncaught exception occured in. However because a Java programmer may provide an UncaughtException handler, the behaviour could quite well be different from the default of terminating the thread.
Not all crashes are due to unhandled exceptions. For your example, the C++ standard says that dereferencing the NULL pointer results in undefined behaviour. In Windows, you can handle problems that crash your program without throwing a C++ exception with structured exception handling (SEH): __try
/__except
/__finally
. In Unix, you can set up special signal handlers.
Also, there is an error in your code. The exception handler for const char *
would only be invoked when an exception of this type is thrown. For standard exceptions, you should catch std::exception
or it's appropriate subclasses. To catch any C++ exception, use catch (...)
.
Actually, you CAN catch system exceptions in C++. There is a compiler option (at least in Visual Studio) that lets you catch access violation exceptions (which is why your program crashes).
Java is more guarded, therefor the illusion of complexity.
Think of the following:
In Java:
int x[10];
int i = 20;
try
{
int k = x[i];
}
catch (ArrayIndexOutOfBoundsException ex)
{
//will enter here
}
Int C++:
int x[10];
int i = 20;
try
{
if ( i >= 10 )
throw new "Index out of bounds";
int k = x[i];
}
catch (...)
{
//now it will enter here
}
It all has to do with whether you want to leave more up to the runtime environment (like in Java's case) or you yourself want to handle things. C++ gives you more control, but you have to pay more attention.
Your Java program would also crash if exceptions wouldn't be handled - think about it, if a method throws an exception explicitly, you can't not handle it, because the compiler doesn't let you. If not explicitly, your program will still crash unless surrounded by try/catch.
If what you're asking why system exceptions can't be handled in C++, I already answered: they can, it's just that, by default, this is turned off.
The point of exceptions, in any language, is, or should be, to handle exceptional cases. But still cases where you can make reasonable assumptions about the global program state, and possibly recover. Programming errors generally mean that you can make no assumptions about the global program state, and must terminate the code as quickly as possible, executing the least additional code (since you don't know what it will do).
In Java, practically everything is reported by means of an exception. Everything from common, expected errors ("file not found" when trying to open a file) to critical internal errors (java.lang.VirtualMachineError). C++ gives you the choice: if you detect a coding error (assertion failure), you can abort the process immediately (generally more appropriate than stubling on in an unknown state); if the "error" is something which will normally occur in everyday operation ("file not found"), you can test the status, or use a return code (again, usually more appropriate than an exception). For a number of situations between the two (e.g. out of memory), C++ uses exceptions.
What is most appropriate in a given application, of course, varies:
there are certainly cases where "file not found" is exceptional (e.g. if
the file is part of the application, which can't run without it), and
warrants an exception. Similarly, in specific cases, a null pointer can
be used to control program logic (if ( ptr == NULL ) ...
) or
correspond to an exceptional case (if ( ptr == NULL ) throw ...
); in
other cases, a null pointer is a programming error
(assert( ptr != NULL)
).
- C++ and Java both have try and catch blocks but Java have one new block finally which always executed after try and catch.
- Java throw only objects but C++ throws data(primitive and pointer & objects).
- C++ have catch(...) { } to catch all exception of all kinds and Java have catch(Exception e) { } to catch all exception .
精彩评论