While I regularly use try/catch, I haven't needed for finally or rethrow. In my quest to broaden my knowledge and potentially improve the apps I work on, how would one use the additional options? I primarily work in Lucee and usually refer to the documentation at cfdocs but specifically for this question cfdocs.org/cftry and the examples don't go into the finally or rethrow... or even throw for that matter (but I'm familiar with throw).
Sample code might help me more than just documentation alone on this.
A finally block is useful when you're managing resources, like a file handle. It can be used with or without a catch block. The example you'll usually see is closing a file handle:
var f = fileopen(filename, "r")
try {
// Some dubious code
} finally {
// f is freed, regardless of any exception thrown within the try block
fileclose(f);
}
The finally block is called regardless of whether an exception is thrown within the try block or not.
rethrow is handy if you ultimately want to bubble the exception up the callstack, but first do something with it. I often find myself logging an exception before rethrowing it to generate a generic error page:
try {
// Something sketchy
} catch (any e) {
writelog(type="Error", file="uhoh.log", text=e.message);
rethrow;
}
rethrow is also useful when you're dealing with weird ColdFusion exceptions that can only be identified by introspection, as opposed to catching them by type. Maybe you want to ignore a certain exception that is thrown whenever sketchy authentication code you didn't write (yeah, this is from experience) encounters an invalidated session, but bubble anything else up:
try {
// Hey, external code, is this user authenticated?
} catch (any e) {
if (e.id != MAGIC_NUMBER_TO_IGNORE)
rethrow;
}
A good resource, as usual, is Ben Nadel's ColdFusion blog.
Related
There are a few SO posts about whether or not declaring main() using function-try-block syntax is valid syntax, and the general consensus seems to be that it's perfectly valid. This left me wondering... is there any reason (performance, style, thread synchronization, multithreading) why one wouldn't use this syntax for main() as a general rule to catch any unhandled exceptions anywhere more gracefully?
Obviously, ideally there won't be unhandled exceptions, but they happen and I think it'd be nice to provide something more informative than the OS-specific default handler. For example, in my case, I'd like to provide a support email address to the user so they can report the crash and have my program submit a log to my cloud-based crash log.
For example, in my case, I'd like to provide a support email address to the user
Well, how are you going to do that in a server with no user-facing interface?
Actually, how are you going to do that even in a process with user-facing components, if you have no way to tell in the catch block what state they're in?
And, for those processes where you can't show the user anything useful (or don't have any concept of a "user" in the first place), what would you do in your catch block that would be better than the default terminate?
As for
... more informative than the OS-specific default handler ...
many OS' default behaviour will be to save a complete snapshot of the process execution state, at the point the un-handled exception is thrown, to a file for debugging. As the developer, I can't think of many default behaviours that would be more informative.
Admittedly I'd prefer something more polished as the end user of a desktop app, but that's a pretty small subset of C++ programs.
You can easily convert
int main() try {
// The real code of main
}
catch (...)
{
}
to
int realMain()
{
// The real code of main
}
int main()
{
try
{
return realMain();
}
catch ( ... )
{
}
}
without losing functionality/behavior.
I am going to guess that whether you use the first version or the second version is a matter of coding practices of a team. From a compiler and run time standpoint, I don't see any semantic difference.
If you happened to have a variable that you want to access in your catch block, you would need the curly braces to provide visibility. But even that could be handled with nested try/catch...
why one wouldn't use this syntax for main() as a general rule to catch
any unhandled exceptions anywhere more gracefully?
compatibility with C.
Sometimes there is no way to handle unhandled exceptions more gracefully.
Obviously, ideally there won't be unhandled exceptions, but they
happen and I think it'd be nice to provide something more informative
than the OS-specific default handler. For example, in my case, I'd
like to provide a support email address to the user so they can report
the crash and have my program submit a log to my cloud-based crash
log.
If unexpected exception happens you can not be sure that it is possible to handle it correctly. What are you going to do if there is a network error exception in your example. And trying to send e-mail causes another exception? There can be other errors when you can not be sure that your data is not corrupted and you can not be sure that your program can run correctly after this error. So if you don't know what error happened it is better to allow your program to crash.
You can implement another "watcher" service that checks if process is running and if it has been crashed it can send e-mail to your users with the logs and core dumps.
If you catch the (otherwise) uncaught object, you won't be able to figure out how the execution reached the throw by inspecting the stack trace, because when exception handler is executed, the stack has already been unwound.
If you let the unexpected exception to be uncaught, you may be able to inspect the stack trace in the terminate handler - this is not guaranteed by the standard, but that's not a big deal since there is no standard way to inspect the stack trace either (in C++). You can either use platform specific API within the program, or an external debugger for the inspection.
So for example in your case, the advantage of not catching the exception would be that you can attach a stack trace to the log entry that you intend to submit.
Also, there are cases where an exception can not be handled by a catch block. For example, when you throw from a destructor that is being executed as a result of throwing an exception. So, to handle these "uncatchable" exceptions, you need a terminate handler anyway, so there is little advantage in duplicating the functionality in the case of uncaught exceptions.
As for the syntax that you use to catch the exception, there is no difference. The case where the function try block is different is a constructor, where it allows catching exceptions thrown by sub object constructors.
I haven't done C++ in a while and my memory is fuzzy, nor have I found a definitive answer so far searching. I'm not talking about rethrowing the caught exception, but rather catching one exception and throwing a different type, such as:
std::unordered_map<int, int> foo;
...
int getFoo(int id)
{
try {
return foo.at(id);
}
catch (std::out_of_range& e)
{
throw MyMoreDescriptiveExceptionType();
}
}
Yes. (have to fill to reach 30 characters)
Yes. Among other things, it allows you to log and re-throw exceptions properly.
Just be careful to re-throw properly. If done incorrectly, you could lose the original stack trace which makes the actual problem much harder to track down.
Yes, it's entirely valid. It's actually quite a common thing to do. For example, a small utility class may throw a fairly generic exception. The code that was calling it may catch that exception, and wrap it in a more specific one, providing more useful information about the context. It will then throw that 'outer' exception.
The same catch-wrap-throw pattern can extended as many levels as you need, until something is able to address the problem or shutdown gracefully.
Yes and that thrown exception will be caught by the next catch in order or next upper level catch and so on
My understanding about exception handling is very limited. While I find it is easy to throw an exception (or I can pack it using expected<T> for later consumption), I have very little idea about what to do with an exception.
Presently my knowledge is limited to
clean my own resources and rethrow the exception to be handled at appropriate location. e.g.
ptr p = alloc.allocate(n);
try
{
uninitialized_copy(first,last,p);//atomic granularity, all or none
}
catch(...)
{
alloc.deallocate(p,n);
throw;
}
But I guess, this can be equivalently transformed in a RAII pattern as
alloc_guard<ptr> p{alloc.allocate(n)};
uninitialized_copy(first,last,p.get());
p.commit();
catch the exception at a top level, compose & print a nice message and exit.e.g.
int main(int argc,char** argv)
{
try
{
app_t the_app(argc,argv);
the_app.run();
}
catch(std::runtime_error& e)
{
//instead of what, I can also compose the mesage here based on locale.
std::cout<<e.what()<<std::endl;
}
}
So, all I do is in a top level function such as main catch the exception and print an appropriate message and close.
While implementing a library with a nice set of API using various external libraries as back end for implementation, I realized that third party library exceptions are part of my API specification, as they cross my library boundary and land in user code!
So, my library API leaked all exceptions from external libraries (and each one having their own exception hierarchy) that I was using to the user code.
This leads to my question, what all can be done when I catch any exception ?
More specifically,
Can I translate the caught exception from external library to my own exception and throw that in a generic way (say the mapping between third party library exception hierarchy and my exception API is provided as a mpl::map) ?
Can I do something more useful than printing a message/call stack, say resume the function at the throw site with different input parameter (say when I get that a file_not_found or disk_error, re-run the function with a different file)?
Any other pattern which is valuable to know?
Thanks
Additional to what nogard said I want to add the following:
Exceptions should be used for exceptional things. Things that should not happen.
If you encounter an exception, log it at least somewhere. This might help you finding a bug.
Try to resolve the error at the point where you caught the exception.
If this is not possible, try to stay in a consistent state where the application can continue.
If this is not possible - think about gracefully terminating.
Notify the user that something out of the ordinary happened.
Final advice - keep your error handling consistent. This includes translating exceptions from third party libraries to your exception hierarchy.
Answers to comments:
2) The exception should contain information about what went wrong. This could be just the type or some additional information. Logging these at the customer allows you to get more information on what actually went wrong beyond to what the customer tells you. Perhaps he misused your application, found another use case or you simply have a bug (e.g. a not initialized variable). But with this extra information you have a location where something went wrong and some information on what went wrong. This helps you to deduce the source of the error and thus find the bug.
3) this actually depends on the error that is occurring. E.g. you try to access a configuration file that is not there --> you create a new one with default values. The client tries to open a database for write access, but it is write protected. You decline opening, return to a valid state and tell the client that the db is write protected. You run out of memory and can't continue? Log this (beware - you have no spare memory so your logging should already have reserved some memory upfront for this use case) and gracefully shut down the application. Perhaps, if possible, notify the client.
Regarding code from other libraries: there's no other way then checking each function call to another library for the exceptions it might return and catching them. Once caught, you can transfer the information from that exception into one of yours and throw that exception (or resolve it somehow else)
This is very big subject.
I doubt you can easily translate third party exceptions into your own exceptions, and moreover personally I see no need to implement this behavior. Since 3rd party library is a part of your implementation, which is not exposed to the public API, why would you expose all of its exceptions (even through some mapping)? If one day you stick to another 3rd party library implementing the same stuff - would you like to redesign whole exception hierarchy? I think not. API of your library must not be fragile, so I would propose not to map external exceptions to your own ones.
You can map 3rd party exceptions to your hierarchy following ways:
Don't wrap anything at all. I mean you don't have to throw anything just because 3rd library does so. You can catch that exception and handle it, or return error code, or change the state appropriately. There are many other possibilities rather than rethrowing always.
You don't have to make one-to-one translations for all 3rd party exceptions. If you use library AAA internally, then you can have single AAAException representing many exceptions coming from that library.
Valuable to know: always catch exceptions by const reference:
catch (const exception & ex)
This subject is very big, I hope my answer helps to understand it.
Answers to the comments:
If I do not map third party exceptions to my own API (need not to be one to one), they leak to client code - No, they don't, that's the whole point! You must catch them inside your library and then decide what to do with catched exceptions: throw your own exception, return error code, notify client listener, log error etc...
try {
3rdpatry.call();
} catch (const 3rdpartyException & ex) {
// throw YourException(ex.what());
// listener.notify(some_error)
// return some_code
}
Catching by const reference is not to prevent slicing at all. There is nice discussion here that explains that.
Top-level catch is usually not enough for larger applications. You need to catch exception when you can do something about it, but there are principally only few ways in what to do with an exception:
Recover if you can. - (e.g.: Check for update -> Network connection could not be opened exception -> ignore and don't download the update now.)
Tell the user to choose how to recover. (e.g.: Save file -> File cannot be created exception -> tell user to choose different filename or cancel)
Log and exit. This is the top-level catch-all scenario.
I've run into a situation with some code I inherited... honestly, I believe the code is written correctly, but this error still seems to manifest.
I'll quickly note that the code is cross-compiled from linux to LynxOS, I'm not sure if that can have anything to do with the error.
Basically, in one specific case:
try {
std::vector<ClassA> x = SomeGeneratingFunction();
//We get to here fine. X may be empty/unpopulated though.
if (x.size() < 1)
{
throw(MyException("It crashed."));
}
}
catch (MyException e)
{
//Handle it.
}
catch (...)
{
//Handle it.
}
We throw given the vector is unpopulated, but for some reason the throw bypasses the catch clauses - both of them. It only seems to happen here - though we woudln't usually do it form an if statement scope, but that should be completely irrelevant since its still in the try scope.
PS: The code below is actually the contents of a function, and exceptions come out of the function when called even though they should all be handled by the catch blocks.
Any ideas how this is possible? And yes, this isn't the real code/exception classes, but the exception class is the simple example you'd google of overloading std::exception, and the SomeGeneratingFunction() does return a good vector, even if it is empty. I cannot provide the real code, but this is exceedingly close barring any little typos I may have made writitng it off the top of my head.
Since the catch (...) clause didn't catch the exception, my answer does not solve the OP's problem. But for others that found this question on SO, maybe my answer is useful, because it explains why the first catch failed.
I had a similar issue where my catch(const std::exception& ex) was just not working. It turned out to be a dumb problem in that I was switching between C# and C++ exceptions, and in C# you need to specify new when you throw your exception, while in C++ you normally don't (but you can, but in this case you are throwing a pointer and not a reference). I was accidentally doing
throw new std::runtime_error("foo");
so
catch(std::exception* ex)
would have caught it but
catch(std::exception& ex)
doesn't. Of course, the solution is just remove the new statement, as that is not the traditional design pattern in C++.
Since you have a spare set of parentheses around the exception object in the throw statement, it looks like a function call. Is there any possibility that you've defined a function called throw? The parameter to the exception constructor keeps this from being a victim of the Most Vexing Parse, but that's a possibility if your actual code differs from your example.
catch (MyException e)
should read:
catch (const MyException &e)
I'm not sure why your throw looks like a function either, kind of bizarre.
Edit:
I've had problems with catches based on something similar, though I agree that it isn't sufficient in this toy case.
The compiler seems off to me, is Try defined as something funny? If it were empty it could make sense if your compiler ignored catch statements with no try.
If you have a function MyException in a smaller scope (possibly even by accident, Most Vexing Parse) then throw MyException("It crashed") will call that function and throw the return value.
Let me slash the problem... Don't use exceptions in C++ unless you want to crash definitely the program. I know exceptions may be quite useful, but they have very poor performances because it raises up an hardware exception which is caught by the operating system kernel. Using return values and error codes can be 500 times faster than throwing and catching exceptions.
I would just rewrite it without using try/catch. Doesn't seem appropriate to use try/catch here anyway. For all you know, exceptions may not work on your target platform.
I want to know, is it a good practice to place complete code inside a try block or I should place only the code which I feel it will cause a specific exception?
And should I catch basic Exception always
Code 1: complete code in try block
myFunction(){
try{
.........
Code with chance of OneException
.............
}catch(OneException e){
............
}catch(Exception e){
..............
}
}
Code 2: Only the Code with chance of Exception in try block
myFunction(){
.......
try{
Code with chance of OneException
}catch(OneException e){
............
}
............
}
Code 3:Should I catch Exception always
myFunction(){
.......
try{
Code chance of OneException
}catch(OneException e){
............
}catch(Exception e){
..............
}
........
}
Out of this (code1, code2 and code3) which one is the best?
I'm mainly concern with java and C++ coding
Generally speaking, you should only catch exceptions you're interested in and which you can handle. That is...catch an exception where you can do something s.t. the user doesn't perceive the problem or when it is explicitly necessary to tell the user about the problem.
For all other exceptions, let them pop up with all their details (stacktrace etc..) which you obviously log. Note, obviously this doesn't mean the user should also see that exception output but rather a generic error.
Told this, I assume that when you write "Code chance of OneException" you know how to handle OneException, but not Exception, right? So then...only handle OneException.
Always catch exactly what you have to and no more. No matter how much we try, we cannot make our code completely "idiot proof". If someone passes you something which will cause some random error, then it is their job to handle it. If our code handles someone else's exception that has far too much risk of being an unexpected side-effect.
As far as what code to place where: code before the line which could throw the Exception will be run either way, so it does not really make sense to have it inside the try block and before the code which throws. Code after the potential exception should be placed between try and catch if and only if it depends on the exception generating code. So, if your database connection call can fail, place all of the database queries inside the try block.
Limiting the "time" spent in a try...catch makes it easier to read and less prone to accidental catching. I can't tell you how many hours have been lost because someone decided to catch an Exception which should have propagated.
a) It is bad practice, to place complete code inside a try block.
a1) Beside of catching exceptions, a try-block is a documentation where an exception might happen. So place it close to the cause, you have in mind.
a2) In bad circumstances, you have a file for reading, and add later one for writing, but your exception (FileNotFoundException) was written only with the first in mind. A lean scope around the problematic places will help you, identifying further problems.
b) Don't catch basic Exception for completeness or to avoid multiple catch blocks. If you want to write to a file, many things can go wrong: Missing permission, illegal file name, no space left on device, ... . If you present the user a generic Message ("Couldn't write file " + name), he doesn't know what to do. Be as specific as possible, and you can inform him, "Only 20 MB left on device " + devicename + "We need another 8 MB (28 MB in total); please free some space and repeat or choose a different device!"). If you catch "Exception", chances are high, that you're thinking of some exception, but another one occurs, and isn't handled correctly, because the catch-block wasn't written with that possibility in mind.
The best chance to find this exception is, to let it pop up, or, to log it, if the logs are controlled on a regular basis.
It can be a difference between developing an application, which is simply used by end users, or by developing an API, which is used by other developers.
In an API, you often want to wrap an exception into an own exception, to make it easier for users of your api to handle it, and if you have an uniform way to handle exceptions. If your code can throw many exceptions, and would lead to ugly client code, where your customer would need to specify a bunch of exceptions over and over again, you often wrap the exceptions and rethrow them:
try {
...
}
catch {FileNotFoundException fnfe}
{
throw new MyApiException (fnfe);
}
catch {PermissionDeniedException pde}
{
throw new MyApiException (pde);
}
catch {IOException ioe}
{
throw new MyApiException (ioe);
}
That way, your client can decide, how to handle the exception, and will find the specific type of exception, if interested, inside your exception.
As Landei points out, in Java 7 there will be a simplified technique, to catch multiple exceptions, but not only such with a common superclass, see this link here
Wrap the code at the point where you really can handle the exception, and where you can handle the error. If you can't handle the error in the function, then do no wrap the code in try/catch block.
I don't know for java, but in c++ you should catch by const reference :
try
{
// code that can throw an exception
}
catch ( const SomeExceptionType & error )
{
// handle the error
}
C++ isn't Java or C# or... where you need catch (or finally) clauses to clean up after yourself. In C++, RAII does that. Consequently, I rarely ever write try/catch statements in C++, to the point where I consider it a code smell.
So, rather than contemplating which style of code you should use in conjunction with try/catch, you should ask yourself whether you need that try/catch at all.