I started using exceptions some weeks ago and now I wonder if there is a way to just throw a warning. This warning shouldn't force the application to exit if it isn't caught. I will give you an example in what situation I would like to use that.
There is a system that appends properties to unique ids. When I somehow try to add a property to a not yet existing id, the system should create that id internally for me, add the property to it afterwards and return the result. Of course this can't be done quietly. But since the application could stay running, I do not want to throw an exception.
How can I notify that something wasn't quite correct, but the system runs on?
Who do you want to notify? The end-user? In which case, just write a suitable message to cerr. Or better, write a wrapper function (e.g. LOG_WARNING()) to do it in a controlled manner. Or better still, use a logging framework.
But since the application could stay running, I do not want to throw an exception.
Note that an exception doesn't have to result in the application terminating. You can catch an exception higher up the stack, and handle the situation appropriately.
No, that's not possible. You can only throw and catch exceptions. If you want to be cheeky you could do
class warning : public std::exception
{
public:
warning(const std::string& msg) {}
const char* what() { return msg.c_str(); } //message of warning
private:
std::string msg;
};
Then you can:
throw warning("this is a warning");
This could be an artificially made up warning system if you want.
While there's no throwing a warning. I believe the functionality you're looking for is available from errno
You can set it to any of the standard errors or make up your own error codes. (Please document them well though.)
This could be useful if your library is meant to be used by other developers. An example of when this might be useful is with a JSON parser. JSON supports arbitrarily large numbers with arbitrary accuracy. So if internally your parser uses doubles to represent numbers if it encountered a number that it couldn't represent then it could round the number to the nearest representable number the set errno=EDOM; (argument out of range) that way, it leaves the decision up to the developers as to whether the rounding will matter. If you want to be super nice you could even add in a way to retrieve the locations of the rounds possibly even with the original text.
All of that said, this should only be used in situations where:
the warning really can be bypassed completely in some scenarios
the root source of the warning is input to the library you're writing
the in some situations the consumer of the library might care about the warning but most of the time wouldn't.
there's not a more suitable way to return the information (like a status passed by reference with an overload that doesn't require the status)
Just print a message to stderr or to your logs.
Related
I have some psuedocode for a function to display a value and get a value
int getValue(){
int value;
// open file
// read line into "value"
if(error occurs){
// if file doesn't open or line was not an integer
/* Normally I would return something such as -1
but -1 in this case would be a valid value*/
value = ?
}
return value;
}
void displayValue(){
int value = getValue();
if(value is valid)
display(value);
}
As described in the code above, I would like to return that there was an error and let displayValue know that there was an error. But i want to accept negative,positive, and 0 from getValue.
Is there a better way to go about this? Does anyone have any advice?
Throw an exception. One of the advantages of C++ over C is that, when you have an error, you don't have to smuggle error codes out of the function, you can just throw an exception. If it's a truly exceptional case, most of the time the caller won't have anything useful to do with it anyway, so forcing them to check for it manually, then pass the error up the call chain is pointless. If they do know what to do with it, they can catch it.
This solution is also more composable. Imagine a scenario where A returns int, B calls A and returns a std::string based on it, and C calls B and returns class Foo based on that. If A has an exceptional condition that requires it to return an error, you can either:
Come up with some way to smuggle the error out of A as an int (or std::optional<int> or std::pair<bool, int> or whatever), then check for and convert that smuggled error to a different smuggled error for B, then check for and convert that to yet another smuggled error for C, then the caller of C still needs to check for that smuggled error and all three layers have to pay the price of the checks every time, even when all three layers succeeded, or...
You throw an exception in A, neither B nor C have anything useful to do with it (so they don't write any additional code at all), and the caller of C can choose to catch the exception and produce a friendlier error message if they so choose.
On modern architectures, the cost in the success case for #2 should be pretty negligible; the failure case might be more costly than the "check at every level case", but for something like "file doesn't exist" or "file contains corrupt data", it hardly matters if performance suffers, since you're probably about to exit the program (so speed doesn't count) or pop a dialog the user needs to respond to (the user is slower than the computer by many orders of magnitude).
There are several error handling approaches in C++:
The traditional way popular in C API's (also used by std::string algorithms) is to reserve at least one value as "invalid", which when returned would signal that there was an error, or that the value represents "no result". In case of error, the C API's would use the global errno to inform what error happened.
One of the features C++ introduced over the C language is exceptions. You can simply throw when error occurs. This is most appropriate for unexpected errors or pre/post-condition violations, rather than "no result exists" type situations.
Yet another way is to return both the value, and information about whether the result is valid. Old fashioned approach might be to return a pair of integer and boolean (or a named class that achieves the same). Alternatively, either value or error state can written into object passed through indirection. std::optional has been introduced into the standard library just for this kind of situation an is a great way of representing lack of result.
Latter approach can be further extended to not only return a boolean, but actual information about the error in similar way to the way exceptions do. The error information can also be wrapped with the value in a "variant" type so that they can share the space, as only one of them can exist at any time. This approach is similar to Maybe type in Haskell. There is a proposal to introduce a template for this purpose into the standard library.
Each of these approaches have their benefits and drawbacks. Choose one that is appropriate for your use case.
One option is to throw an exception when an error occurs. It's highly dependent on the rest of your project. Are Exceptions used all around ? Personally, I prefer more conventional old-school approaches. Mostly because people will start throwing exception everywhere, where it's not really exceptional and then it makes debugging much harder as the debugger keeps stopping for non-exceptional situations.
Another option is to return a pair std::pair<bool, int>. Some people love it, some people hate it.
My preference would be bool attemptGetValue(int& outValue). You return false if there's an error, in which case you don't touch outValue. Your return true otherwise and modify outValue
You can also use std::optional, but old timers might not be familiar wiht it.
Other than throwing an exception, returning a std::optional, or a std::pair, there is a precedent here: std::string::npos is normally set to a particularly large std::string::size_type value, normally -1 (wrapped around of course) and is used by some std::string functions to indicate a failure.
If you're willing to give up one legitimate return value then you could do something similar in your case. In reality though, typical (perhaps all) strings will be significantly smaller than npos; if that's not the case for you then perhaps one of the alternatives already mentioned would be better.
I can only think of the following situations where std::exception::what() is used:
For debug purpose. In my Visual Studio to see e.what() I have to manually add it to the watch list. Isn't it better to have a member std::string (so the debugger directly shows it in the object inspector), and only include it in non-NDEBUG builds? At least they should disable what() in NDEBUG builds.
Output it, e.g. MessageBox(e.what()) or cout << e.what(). As far as I know these messages are useless for many users. For example when I try to rename a file that doesn't exist:
boost::filesystem::rename: 系统找不到指定的文件。: "D:\MyDesktop\4", "D:\MyDesktop\5"
(The Chinese words means "The system cannot find the file specified.") How can the users decrypt the mixed things? Also, it is a const char* instead of something like const platform_char*, which may have unicode problems in Windows.
Extract data from it, e.g. std::regex_match(e.what()...). I think it's a terrible idea that shows design flaws.
So where should I use std::exception::what()? Is it useless?
A programmer is supposed to derive a class from std::exception and taylor what() to the specific requirements. Then it can be very useful.
It's also useful to report something back (e.g. in plain text for logging), which is why the standard mandates a concrete std::exception::what() rather than a pure virtual function.
what() is generic in the sense that it means what you want it to mean for your own exception classes. In many cases it is used only for logging, but in other cases it may provide information that can be used to recover from an exceptional situation.
So where should I use std::exception::what()? Is it useless?
The error message of std::exception is a char* because it's supposed to be an as-simple-as-possible user-facing diagnostics message giving details on the error.
For boost::system_error (and std::system_error), you can also get the OS-level error code (for which the user-friendly message is "file not found").
Valid uses:
if you want to identify the error type, catch the specialization std::system_error or boost::system_error and perform a switch/if on the code() function (i.e. instead of running a regex on the message).
if you want to display an explanation of the error for diagnostics (logging) or user friendliness (to console/GUI) just display the error message (what()).
std::exception is a base class (i.e. it has a virtual destructor). If you implement your own exception classes, follow the same pattern as std::system_error: use an error code to easily identify an error, and create your exception's base class (std::exception, std::runtime_error or std::logic_error usually) with a text message depending on the error type.
Ultimately, the type of the error message is char* instead of std::string, wstring or your-platform-specific-char-type because it sacrifices flexibility for reliability: with a char* everybody knows how to use it, that it has no encoding (except ASCII), that it's null terminated and once allocated, it does not fail (it doesn't generate new exceptions).
Using something that could fail (in any way) when constructing an exception would be disastrous: you would fail while creating/using a diagnostics message of your error handling code.
This means you could either not throw the exception (and your application will remain in an invalid state), or throw an exception while creating an exception instance (you really don't want that as it would discard the exception you wanted to throw (hide errors) or throw an exception with a missing or corrupted error code (which could waste months of development time in various projects to track down the wrong error).
Consider this example (unnecessarily complicated, but it makes a point):
int * p = new(nothrow) int(10); // I want to throw a complicated
// string message exception
if(nullptr == p)
throw complicated_exception(std::string("error message here"));
The throw line will presumably fail: the application has so little memory available that it won't even allocate an int*, let alone a string. The result of this code is that in low memory conditions I will still get a std::out_of_memory error - one generated by std::string constructor.
std::exception is a good implementation: it provides a minimal extendable interface with a good management/restriction of failure points and it gives a good interface for extensions (such as std::system_error).
I am designing a cross-platform application protection library to communicate with a dongle. The dongle is able to send and receive blocks of data, to create and delete directories and files inside the dongle's internal file system, etc. To put it simple, the main dongle object has methods to implement all of these functionalities. Unfortunately, any of these methods may fail. Right now I am thinking about what to do if they do :)
The most obvious solution is to return a boolean type result from all of these methods to indicate if they fail or success. However, this leads to a loss of details about the nature of an error.
The next possible solution is to return an error code, but there will be more then 30 types of errors. Also, I will need to design a separate function to convert all of these return codes to a more readable string representation.
The third solution is to return a boolean type result, but to keep an error state object in the main dongle object so it will be possible to retrieve it using GetLastError() like method. I am considering about using this one.
Now is my question. Are there any other reasonable error representation and handling patterns and what do you suggest me to use in my case?
Thanks,
Ilya
Of the options you have presented, the best is to use return codes. Typically a return code of zero indicated success, and each other return code has its own positive integral value. 30 error conditions isn't many. As you've said, you'll have to write code to translate these codes to something human-readable, but you have to do this anyway.
I would consider writing an exception hierarchy to do this instead of error codes, however. Exceptions can be more expressive than return codes, and the code can be cleaner if done properly. You would typically design your library so that there is a different exception class for each type of error return condition, each derived ultimately from std::exception. The what() method gives you a place to put the human-message building, and the type of the exception itself describes the error.
There are those who will tell you that exceptions are "only" for exceptional circumstances, like your computer caught fire, or something. This is a hotly debated assertion. I'll tell you that is nonsense. Just because it is named "exception" doesn't mean your computer has to catch fire in order to use it. Exceptions give you a lot of benefits, one of the biggest being stack unwinding. Preventing yourself from using them simply because of some arbitrary line where errors are "bad enough" is silly.
You could also try using std::exception. It allows you to say what the error is and the nature behind it.
In C++, RAII is often advocated as a superior approach to exception handling: if an exception is thrown, the stack is unwound, all the destructors are called and resources are cleaned up.
However, this presents a problem with error reporting. Say a very generic function fails, the stack is unwound to the top level and all I see in the logs would be:
Couldn't read from socket: connection reset by peer.
...or any equally generic message. This doesn't say much about the context from which the exception is thrown. Especially if I'm running something like an event queue processing loop.
Of course I could wrap every call to socket reads with a try/catch block, catch the exception, construct a new one with more detailed context information and re-throw it, but it defeats the purpose of having RAII, and is slowly but surely becoming worse than handling return error codes.
What's a better way for detailed for error reporting in standard C++? I'm also open to suggestions involving Boost.
As James McNellis suggested here, there is a really neat trick involving a guard object and the std::uncaught_exception facility.
The idea is to write code like this:
void function(int a, int b)
{
STACK_TRACE("function") << "a: " << a << ", b: " << b;
// do anything
}
And have the message logged only in case an exception is actually thrown.
The class is very simple:
class StackTrace: boost::noncopyable // doesn't make sense to copy it
{
public:
StackTrace(): mStream() {}
~StackTrace()
{
if (std::uncaught_exception())
{
std::cout << mStream.str() << '\n';
}
}
std::ostream& set(char const* function, char const* file, unsigned int line)
{
return mStream << file << "#" << line << " - " << function << " - ";
}
private:
std::ostringstream mStream;
};
#define STACK_TRACE(func) \
StackTrace ReallyUnwieldyName; \
ReallyUnwieldyName.set(func, __FILE__, __LINE__)
One can use __PRETTY_FUNC__ or equivalent to avoid naming the function, but I have found in practice that it was too mangled / verbose for my own taste.
Note that you need a named object if you wish it to live till the end of the scope, which is the purpose here. We could think of tricky ways to generate a unique identifier, but I have never needed it, even when protecting narrower scope within a function, the rules of name hiding play in our favor.
If you combine this with an ExceptionManager (something where exceptions thrown register themselves), then you can get a reference to the latest exception and in case of logging you can rather decide to setup your stack within the exception itself. So that it's printed by what and ignored if the exception is discarded.
This is a matter of taste.
Note that in the presence of ExceptionManager you must remain aware that not all exceptions can be retrieved with it --> only the ones you have crafted yourself. As such you still need a measure of protection against std::out_of_range and 3rd party exceptions.
Say a very generic function fails, the stack is unwound to the top level and all I see in the logs would be [...]
What's a better way for detailed for error reporting in standard C++?
Error handling isn't local to a class or library - it is a application level concern.
Best I can answer you question is that the error reporting should be always implemented by looking first and foremost at the error handling. (And the error handling also including the handling of the error by the user.) Error handling is the decision making about what has to be done about the error.
That is one of the reasons why error reporting is an application level concern and strongly depends on the application workflow. In one application the "connection reset by peer" is a fatal error - in another it is a norm of life, error should be silently handled, connection should be reestablished and pending operation retried.
Thus the approach you mention - catch the exception, construct a new one with more detailed context information and re-throw it - is a valid one too: it is up to the top level application logic (or even user configuration) to decide whether the error is really an error or some special (re)action has to taken upon the condition.
What you have encountered is one of the weaknesses of so called out-of-line error handling (aka exceptions). And I'm not aware of any way to do it better. Exceptions create a secondary code path in the application and if error reporting is vital the design of the secondary code path has to treated just like the main code path.
Obvious alternative to the out-of-line error handling is the in-line error handling - good ol' return codes and log messages on the error conditions. That allows for a trick where application saves all low-severity log messages into internal (circular) buffer (of fixed or configurable size) and dumps them into the log only if high-severity error happens. This way more context information is available and different layers of application do not have to be actively aware of each other. That is also standard (and sometimes literally "standard" - mandated by law) way of error reporting in application fields like safety and mission critical software, were one is not allowed to miss errors.
I've never actually done this, but you could roll your own "stacktrace":
struct ErrorMessage {
const char *s;
ErrorMessage(const char *s) : msg(s) {}
~ErrorMessage() { if (s) std::cout << s << "\n"; }
void done() { s = 0; }
};
void someOperation() {
ErrorMessage msg("Doing the first bit");
// do various stuff that could throw
msg = "Doing the second bit";
// do more stuff that could throw
msg.done();
}
You can have several levels of this (although not necessarily use it at every level):
void handleFoo() {
ErrorMessage msg("Handling foo event");
someOperation();
msg.done();
}
And add more constructors and members:
void handleBar(const BarEvent &b) {
ErrorMessage msg(std::stringstream("Handling bar event ") << b.id);
someOperation();
msg.done();
}
And you needn't write the messages to std::cout. It could be to some logging object, and the object could queue them, and not actually output them to the log unless the catch site tells it to. That way, if you catch an exception that doesn't warrant logging, nothing is written.
It's not pretty, but it's prettier than try/catch/throw or checking return values. And if you forget to call done on success (for example if your function has multiple returns and you miss one), then you will at least see your mistake in the logs, unlike a resource leak.
[Edit: oh, and with a suitable macro you can store __FILE__ and __LINE__ in the ErrorMessage.]
You could add a call stack to your exception. I'm not sure how good this works for release builds but works like a charm with debug. You could do this in the constructor of your exception (to encapsulate it). See here for a starting point. This is possible as well on Linux - eventhough I dont remember how exactly.
I use RAII and exceptions and just have various unit-test-like assert statements throughout the code - if they fail, the the stack unwinds to where I can catch and handle them.
#define APP_ASSERT_MSG(Class,Assertion,szDescription) \
if ( !(Assertion) ) \
{ \
throw Class(__LINE__,__FILE__,szDescription); \
}
For most of my particular use case, all I care about is logging debug information, so my exception has the file and line number in it along with an error message (message is optional as I have an assert without it as well). You could easily add FUNCTION or an error code of some type for better handling.
I can then use it like this:
int nRet = download_file(...);
APP_ASSERT_MSG(DownloadException == ERR_OK, "Download failed");
This makes error handling and reporting much easier.
For really nasty debugging, I used GCC's function instrumentation to keep a trace list of what's going on. It works well, but slows down the app quite a bit.
What I do regularly, FWIW, is not use exceptions, but rather explicit error handling in a standard format (ie: using a macro). For example:
result = DoSomething();
CHECK_RESULT_AND_RETURN_ON_ERROR( result );
Now, obviously, this has many limitations design-wise:
Your return codes may need to be somewhat uniform
Code is cluttered with macros
You may need many macros for various check conditions
The upside, though, is as Dummy00001 said: you can effectively generate a stack trace on demand in the event of a serious error, by simply caching the results. I also use this paradigm to log all unexpected error conditions, so I can adjust the code later to handle unexpected conditions which occur "in the wild".
That's my 2c.
Here's how I handle error reporting in my libraries (this may or may not suit your situation).
First, as part of your design you want a "core" or "system" library that all this common logic will sit in. All you other libraries will then link to the core and use its error reporting APIs, so your whole system has a single compact chunk of logic for handling this mess.
Inside the core, provide a set of logging MACROS such as "LogWarning" and "LogFatal" with documented behavior and expected usage- for example, LogFatal should trigger a hard abort of the process but anything lower than "LogError" is simply advisory (does nothing). The macros can provide a "printf" interface that automatically appends the "LINE", "FILE", and "FUNC" macros as arguments to the underlying singleton object that handles your error reporting.
For the object itself I'll defer to you. However, you want public APIs that configure your "drains"- e.g. log to stderr, log to logfile, log to MS Services log, etc. You also want the underlying singleton to be thread safe, re-entrant where possible, and very robust.
With this system, you can make "exception reporting" ONE MORE DRAIN TYPE. Just add an internal API to that error manager object that packages your logged message as an exception, then throws it. Users can then enable AND DISABLE exceptions-on-error behavior in your code with ONE LINE in their apps. You can put try-catches around 3rd party or system code in you libraries that then calls a "Log..." macro in the catch clauses to enable clean re-throw behavior (with certain platforms and compiler options you can even catch things like segfaults using this).
I've programmed C and C++ for a long time and so far I've never used exceptions and try / catch. What are the benefits of using that instead of just having functions return error codes?
Possibly an obvious point - a developer can ignore (or not be aware of) your return status and go on blissfully unaware that something failed.
An exception needs to be acknowledged in some way - it can't be silently ignored without actively putting something in place to do so.
The advantage of exceptions are two fold:
They can't be ignored. You must deal with them at some level, or they will terminate your program. With error code, you must explicitly check for them, or they are lost.
They can be ignored. If an error can't be dealt with at one level, it will automatically bubble up to the next level, where it can be. Error codes must be explicitly passed up until they reach the level where it can be dealt with.
The advantage is that you don't have to check the error code after each potentially failing call. In order for this to work though, you need to combine it with RAII classes so that everything gets automatically cleaned up as the stack unwinds.
With error messages:
int DoSomeThings()
{
int error = 0;
HandleA hA;
error = CreateAObject(&ha);
if (error)
goto cleanUpFailedA;
HandleB hB;
error = CreateBObjectWithA(hA, &hB);
if (error)
goto cleanUpFailedB;
HandleC hC;
error = CreateCObjectWithA(hB, &hC);
if (error)
goto cleanUpFailedC;
...
cleanUpFailedC:
DeleteCObject(hC);
cleanUpFailedB:
DeleteBObject(hB);
cleanUpFailedA:
DeleteAObject(hA);
return error;
}
With Exceptions and RAII
void DoSomeThings()
{
RAIIHandleA hA = CreateAObject();
RAIIHandleB hB = CreateBObjectWithA(hA);
RAIIHandleC hC = CreateCObjectWithB(hB);
...
}
struct RAIIHandleA
{
HandleA Handle;
RAIIHandleA(HandleA handle) : Handle(handle) {}
~RAIIHandleA() { DeleteAObject(Handle); }
}
...
On first glance, the RAII/Exceptions version seems longer, until you realize that the cleanup code needs to be written only once (and there are ways to simplify that). But the second version of DoSomeThings is much clearer and maintainable.
DO NOT try and use exceptions in C++ without the RAII idiom, as you will leak resources and memory. All your cleanup needs to be done in destructors of stack-allocated objects.
I realize there are other ways to do the error code handling, but they all end up looking somewhat the same. If you drop the gotos, you end up repeating clean up code.
One point for error codes, is that they make it obvious where things can fail, and how they can fail. In the above code, you write it with the assumption that things are not going to fail (but if they do, you'll be protected by the RAII wrappers). But you end up paying less heed to where things can go wrong.
Exception handling is useful because it makes it easy to separate the error handling code from the code written to handle the function of the program. This makes reading and writing the code easier.
return an error code when an error condition is expected in some cases
throw an exception when an error condition is not expected in any cases
in the former case the caller of the function must check the error code for the expected failure; in the latter case the exception can be handled by any caller up the stack (or the default handler) as is appropriate
Aside from the other things that were mentioned, you can't return an error code from a constructor. Destructors either, but you should avoid throwing an exception from a destructor too.
I wrote a blog entry about this (Exceptions make for Elegant Code), which was subsequently published in Overload. I actually wrote this in response to something Joel said on the StackOverflow podcast!
Anyway, I strongly believe that exceptions are preferable to error codes in most circumstances. I find it really painful to use functions that return error codes: you have to check the error code after each call, which can disrupt the flow of the calling code. It also means you can't use overloaded operators as there is no way to signal the error.
The pain of checking error codes means that people often neglect to do so, thus rendering them completely pointless: at least you have to explicitly ignore exceptions with a catch statement.
The use of destructors in C++ and disposers in .NET to ensure that resources are correctly freed in the presence of exceptions can also greatly simplify code. In order to get the same level of protection with error codes you either need lots of if statements, lots of duplicated cleanup code, or goto calls to a common block of cleanup at the end of a function. None of these options are pleasant.
Here's a good explanation of EAFP ("Easier to Ask for Forgiveness than Permission."), which I think applies here even if it's a Python page in Wikipedia. Using exceptions leads to a more natural style of coding, IMO -- and in the opinion of many others, too.
When I used to teach C++, our standard explanation was that they allowed you to avoid tangling sunny-day and rainy-day scenarios. In other words, you could write a function as if everything would work ok, and catch the exception in the end.
Without exceptions, you would have to get a return value from each call and ensure that it is still legitimate.
A related benefit, of course, is that you don't "waste" your return value on exceptions (and thus allow methods that should be void to be void), and can also return errors from constructors and destructors.
Google's C++ Style Guide has a great, thorough analysis of the pros and cons of exception use in C++ code. It also indicates some of the larger questions you should be asking; i.e. do I intend to distribute my code to others (who may have difficulty integrating with an exception-enabled code base)?
Sometimes you really have to use an exception in order to flag an exceptional case. For example, if something goes wrong in a constructor and you find it makes sense to notify the caller about this then you have no choice but to throw an exception.
Another example: Sometimes there is no value your function can return to denote an error; any value the function may return denotes success.
int divide(int a, int b)
{
if( b == 0 )
// then what? no integer can be used for an error flag!
else
return a / b;
}
The fact that you have to acknowledge exceptions is correct but this can also be implemented using error structs.
You could create a base error class that checks in its dtor whether a certain method ( e.g. IsOk ) has been called. If not, you could log something and then exit, or throw an exception, or raise an assert, etc...
Just calling the IsOk on the error object without reacting to it, would then be the equivalent of writing catch( ... ) {}
Both statement would display the same lack of programmer good will.
The transport of the error code up to the correct level is a greater concern. You would basically have to make almost all methods return an error code for the sole reason of propagation.
But then again, a function or method should always be annotated with the exceptions it can generate. So basically you have to same problem, without an interface to support it.
As #Martin pointed out throwing exceptions forces the programmer to handle the error. For example, not checking return codes is one of the biggest sources of security holes in C programs. Exceptions make sure that you handle the error (hopefully) and provide some kind of recover path for your program. And if you choose to ignore an exception rather than introduce a security hole your program crashes.