I inherited a C++ project with a function defined like so:
void myDoc::parseDoc(string& path) throw(docError);
The parseDoc function calls a library that throws libError, and the main function that calls parseDoc catches both docError and libError and logs them. parseDoc doesn't throw any exceptions itself, but I would've expected the libErrors from the library to still get caught by main. They don't - I just get a core dump with nothing useful on the stack.
I tried various changes to parseDoc. Some of them get libError passed up the chain. and some don't:
catch libError and rethrow it - doesn't work
catch libError and copy it to a docError and throw that - works
specify throw(docError, libError) and not catch anything - works
remove the throw() from the function definition and not catch anything - works
So my question is - does adding a throw(docError) to this function definition specifically prevent other exceptions from being passed up the stack to the caller? If so, why would anyone want to do that? And if not specifying that a function throws exceptions just works the way I always thought exceptions were supposed to work, what's the point of the throw(e) specification in the first place?
Yes, a throw specification does not allow any exceptions except the specified to escape the function.
As for why anyone would want that, the idea is documentation, showing exactly which exceptions the function will throw.
However, in reality, the concept proved to be so useless that throw specifications were (or will be, not sure about the exact status) actually removed in a newer version of C++. So the correct action to take is number 4, removing the specification.
Related
I was trying to implementing a nd-array in C++ like numpy in python, but I do not know how to handle the problems(or exceptions?) like "indices out of range". Should I just use the assert to check the parameters at the beginning of the functions, or use try/catch/throw mechanisms?
BTW, if I use assert, how to print the error messages like "the input index is out of range" to users instead of just "assert at line 5 failed" assertions.
the macro I am using right now to check the index:
#define RANGE_CHECK(total, index) assert(total > index)
The method used by the standard library is to throw std::out_of_range, from functions named at, and to have undefined behaviour in functions named [].
Asserts are for things that never ever should happen and the only way to handle them is to terminate the program. Basically you never ever want to use them (although sometimes it's the only way).
So go with exceptions. The std lib already has a number of excpetions defined that you can throw for stuff like index out of range. Use them.
With exceptions the default will be to terminate the program, just like with assert. But unlike an assert the program can try/catch the exception and handle the error if they like. It's then their job to print a more meaningfull error message if they so desire.
C++ is the world of lazy programmers; they normally tend to stay off exception handling as long as possible. As #Caleth mentioned earlier, following std conventions, one can provide a none-throwing operator[] as well as a throwing at. But boosters proposed a postponed exception-handling approach throughout either of the following:
std::optional:
Return a std::optional<T> instead of T:
std::optional<T*> arr::at(size_t)noexcept;
Provide a none-throwing overload - alongside the throwing function - with an extra std::error_condition reference argument:
`T* arr::at(size_t) throw(std::out_of_range);
T* arr::at(size_t, std::error_condition &ec) noexcept;`
return a pair of value and std::error_condition:
std::pair<T*,std::error_condition> arr::at(size_t)noexcept;
I am compiling my program with a 3rd party library. That library contains an error callback if an error occurs internally. Inside that error callback I am throwing an exception and I have a unit test to verify that when I do something invalid that the exception is thrown. This all works beautifully in Windows, but when I test this in linux (fedora) I am getting an abort from an uncaught exception.
I tried wrapping my call directly with a try-catch block but no luck. ( Also, all my code is running within the google test framework which also normally catches exceptions ). The only thing that seems to catch the exception is if I wrap the throw statement in a try block directly within the error callback.
Does anyone have any idea why this would happen and if there is a way to catch the exception?
When you interface with third-party libraries you usually have to catch all exception on the border between your code and their code:
int yourCallback( params )
{
try {
doStuff( params );
return Okay;
} catch (...) {
return Error;
}
}
The reason is you can't be sure that library is written in C++ or it uses the very same version of C++ runtime as your code uses.
Unless you're completely sure that code can deal with your exceptions you can't propagate exceptions to third-party code. The extreme example is COM where both your code and "other code" can be in whatever language and with whatever runtime and you are not allowed to let exceptions propagate through COM boundary.
Usually you should not throw exceptions "through" code you do not know anything about. It might be C code, which will not even clean up after itself.
How to deal with your concrete problem would require concrete information about the 3rd-party library you are interfacing with. What is that callback there for? To give you a chance to fix stuff? To inform you that an error occurred? Can you cancel whatever operation it is called from?
One way to deal with such a scenario is to store some information somewhere when the callback is called and check for that information when the actual processing finishes from your function that calls into that library.
Regarding the terminate handler,
As i understand it, when something bad happens in code, for example when we dont catch an exception,
terminate() is called, which in turn calls abort()
set_terminate(my_function) allows us to get terminate() to call a user specified function my_terminate.
my question is: where do these functions "live" they don't seem to be a part of the language, but work as if they are present in every single cpp file, without having to include any header file.
If there are default handler functions for terminate and abort that you did not install yourself, they'd have to be in the runtime library provided by your compiler.
Normally, every program is linked against the runtime library (e.g. glibc under Linux). Among other reasons, this is because the runtime library contains "hidden" code for essential things, e.g. code that calls your main function at startup.
I don't see why you think there is no need to include a header:
int main() {
abort();
}
gives the following error for me:
error: 'abort' was not declared in this scope
Neither C nor C++ have any "special" functions - if you want to use a function, you must declare it somehow. These two live in the C++ Standard Library, and are declared in cstdlib and exception. Of course, these headers themselves may be #included by other headers, thus making the functions available, but this is not specified by the standard.
set_terminate - terminate handler function
Sets f as the terminate handler function.
A terminate handler function is a function automatically called when the exception handling process has to be abandoned for some reason. This happens when a handler cannot be found for a thrown exception, or for some other exceptional circumstance that makes impossible to continue the handling process.
The terminate handler by default calls cstdlib's abort function
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.
Exceptions in C++ don't need to be caught (no compile time errors) by the calling function. So it's up to developer's judgment whether to catch them using try/catch (unlike in Java).
Is there a way one can ensure that the exceptions thrown are always caught using try/catch by the calling function?
No.
See A Pragmatic Look at Exception Specifications for reasons why not.
The only way you can "help" this is to document the exceptions your function can throw, say as a comment in the header file declaring it. This is not enforced by the compiler or anything. Use code reviews for that purpose.
You shouldn't be using an exception here. This obviously isn't an exceptional case if you need to be expecting it everywhere you use this function!
A better solution would be to get the function to return an instance of something like this. In debug builds (assuming developers exercise code paths they've just written), they'll get an assert if they forget to check whether the operation succeded or not.
class SearchResult
{
private:
ResultType result_;
bool succeeded_;
bool succeessChecked_;
public:
SearchResult(Result& result, bool succeeded)
: result_(result)
, succeeded_(succeeded)
, successChecked_(false)
{
}
~SearchResult()
{
ASSERT(successChecked_);
}
ResultType& Result() { return result_; }
bool Succeeded() { successChecked_ = true; return succeeded_; }
}
Outside the scope of your question so I debated not posting this but in Java there are actually 2 types of exceptions, checked and unchecked. The basic difference is that, much like in c[++], you dont have to catch an unchecked exception.
For a good reference try this
Chris' probably has the best pure answer to the question:
However, I'm curious about the root of the question. If the user should always wrap the call in a try/catch block, should the user-called function really be throwing exceptions in the first place?
This is a difficult question to answer without more context regarding the code-base in question. Shooting from the hip, I think the best answer here is to wrap the function up such that the recommended (if not only, depending on the overall exception style of the code) public interface does the try/catch for the user. If you're just trying to ensure that there are no unhandled exceptions in your code, unit tests and code review are probably the best solution.
There was once an attempt to add dynamic exception specifications to a function's signature, but since the language could not enforce their accuracy, they were later depreciated.
In C++11 and forward, we now have the noexcept specifier.
Again, if the signature is marked to throw, there is still not requriement that it be handled by the caller.
Depending on the context, you can ensure that exceptional behaviour be handled by coding it into the type system.
See: std::optional as part of the library fundamentals.
Is there a way one can ensure that the
exceptions thrown are always caught
using try/catch by the calling
function?
I find it rather funny, that the Java crowd - including myself - is trying to avoid checked Exceptions. They are trying to work their way around being forced to catch Exceptions by using RuntimeExceptions.
Or you could start throwing critical exceptions. Surely, an access violation exception will catch your users' attention.