I am C# programmer but now I want to get more into C++.
I know the basics of C++ but I don't know how to handle errors.
For example: I am writing a library. I create an constructor which requests an integer as an argument.
If that integer is bigger than 50, it is an error.
In C# I would throw an ArgumentOutOfRange exception, but what should I do in C++?
In C# I would throw an ArgumentOutOfRange exception but what should I do in c++?
First you should consider if that should not be a precondition of your function, leaving the responsibility of checking whether the value is in range to the caller.
If you decide for this option, then invoking the function with an out-of-range value would be undefined behavior, and inside the function you could just have a debug assertion to help you spot possible misuses - without the need of throwing any exception.
If you decide that the function should have a wide contract, on the other hand, and react in a well-defined way by throwing an exception when the argument is outside the permitted range, then you could throw an std::out_of_range exception.
For example: I am writing a libary [...]
If you are writing a library, meaning that you do not know the exact requirements of your clients in terms of performance and robustness, you may consider providing two such functions - one with a wide contract that throws exceptions, and one with a narrow contract that assumes the client provides meaningful input.
This way, the user of your library could decide based on their use cases whether or not it is OK to pay for the overhead of checking the correctness of the input each time your function is called.
This is, for instance, the strategy adopted by the C++ Standard Library for std::vector, which provides a non-throwing operator[] with a narrow contract for accessing elements of the collection based on the index (this function has undefined behavior if the index is out-of-bounds), and a member function at() that performs index checking and throws an exception if the index is out-of-bounds.
It depends on whether an integer larger than 50 could possibly be passed to the constructor as part of normal program flow, or whether that's an exceptional condition. But in general the only way to have object construction fail is by throwing an exception.
Your user code might look like this:
int n = parse_user_input()
if (n < 50)
{
Foo x(n);
x.do_cool_stuff();
}
else
{
// report user error
}
That is, you don't actually use exceptions for normal control flow. With that sort of code pattern, it would be perfectly fine for Foo::Foo(int) to throw an exception if the argument were out of range.
You can find useful standard exception classes in <stdexcept>.
The same thing as in C#: throw an exception. This is the only way to prevent an object from being constructed.
std::invalid_argument is a good standard choice regarding what to throw.
From the C++ FAQ: [17.8] How can I handle a constructor that fails?
Excerpt:
Throw an exception.
Constructors don't have a return type, so it's not possible to use
return codes. The best way to signal constructor failure is therefore
to throw an exception. If you don't have the option of using
exceptions, the "least bad" work-around is to put the object into a
"zombie" state by setting an internal status bit so the object acts
sort of like it's dead even though it is technically still alive.
So, throwing std::invalid_argument or std::out_of_range would be perfectly acceptable for your situation. You could also throw a custom exception if that would be beneficial in your situation. In the C++ FAQ see: [17.12] What should I throw?
Related
I understand that writing exception-safe code basically means taking into account what part of the code can throw exception, so that you can offer some guarantee about the behavior when an exception is indeed thrown. In particular, I take it that the best is to write code with a nothrow guarantee if the situation permits it.
The thing is, how do I know that my code cannot throw?
More precisely:
Let's say that all functions that I use cannot throw (they have the noexcept(true) specifier, which I check with static_assert, and are implemented to ensure it).
Knowing that, can something still throw, like operations on basic types or function calls throw (not the function itself, but the function call)?
Can an error occur without leading to an exception (for example, I heard that dividing an int by zero results in an error, but does not throw)
Both Java and C#, and probably many other languages too, have a predefined exception class that is thrown when a null parameter is used where it should not. Is there anything similar in C++? If not, is there another predefined exception I can use or should I define my own one?
Dereferencing a NULL pointer is undefined behaviour in C++ - which means the code can appear to work. An exception isn't guaranteed to be thrown. You can use the
std::invalid_argument
exception (provide a meaningful value to it - "p is NULL"), but you'll have to do the check yourself.
Usually, in C++ (or C for that matter), you never dereference a NULL pointer. Doing this has undefined behavior (likely a segfault on any implementation I know of, but anything could happen according to the standard). It's probably a bad thing in other languages as well, but I don't know those enough to assert that.
It's best to prevent the situation than to try to recover from it (which can't be done in C or C++ anyway).
The usual pattern to prevent some related programmer errors is to use assert() inside function bodies such as:
int foo(int* myint)
{
// Ensure myint is not NULL
assert(myint);
// Do something with myint
(*myint)++;
return *myint;
}
Such assert() calls are completely ignored on release builds and thus have no cost in production. They just help the development. On debug builds, and if the condition is not met, the program aborts immediately with a very explicit error message. Running it through a debugger, you can easily check the call stack to investigate for the exact reason.
There is no standard exception in C++ for dereferencing a NULL pointer.
If you want it, you can implement it yourself. On UNIX set up a SIGSEGV signal handler and throw an exception from the handler. On Windows, use the _set_se_translator() API to install a "Structured Exception" handler.
In nearly all cases that involve wrongly using a null pointer (esp., derefencing it), the C++ Standard simply leaves the behaviour undefined. No specific exception type is provided for (and no exception will be thrown).
One possible exception to this rule comes to mind, though. std::function, which is a C++11 standard-library template that can be used to wrap functions, can be assigned a null pointer:
std::function<void(int)> func = nullptr;
And if you then make an attempt to call the function wrapped by it by doing func(arg); for some argument arg, it will throw a std::bad_function_call exception.
This is, of course, not fully equivalent to the null pointer exceptions of other languages, because it is far less generally applicable.
FTR, in C# you don't use NullReferenceExceptions for anything unless you want to get stabbed by your team mates. There is a ArgumentNullException instead for rejecting null arguments. NREs are meant to be thrown by the runtime, not you.
But note that there is no actually advantage of this over an assertion because you should not be catching one of these: if they are thrown, they indicate a bug. These are what Eric Lippert calls boneheaded exceptions and they are your own darn fault, and there is nothing your code should be doing specifically with them.
Under C++ dereferencing null pointer will result in undefined behaviour, what mostly ends application with segmentation fault. Under Visual Studio you can use extensions like Structured Exception Handling (SEH), that allow to catch null pointer dereferencing.
You can wrap a pointer in a template class which provides a limited interface to the pointer. It can do a nullptr check whenever you access the pointer, and throw an exception.
I have found out that C++ standard functions show very different behavior when having an exception. This seem to contradict its touting of "try/throw/catch". Can anyone please briefly explain what are the C++ designer's reasoning behind these choices?
Do nothing, for example, try to pop() a stack when it is empty (instead of throw a range_error), do sqrt(-1) (instead of throw a domain_error)
Return a zero pointer: for example, when doing illegal pointer downcasting (interesting, doing an illegal reference downcasting will throw a bad_cast)
Throw an exception, but this appear to a minority of functions, for example, substr()
Give user a choice of whether to throw an exception, for example, new() will throw bad_alloc() when out of memory, but you can also choose (nothrow) as an option of new().
Most of the behaviour of C++ library functions can be explained by the general C++ philosophy "you don't pay for what you don't use". That means that any particular construction shouldn't incur any unneeded overhead when you use it correctly.
Optionally, more expensive, checked versions may exist, such as std::vector::at(), but it is up to you whether or not to use them.
The example of stack::pop() and sqrt() shows this philosophy in action: In order to throw an exception on error, you would always have to check whether the call is valid. This check is unnecessary if you already know that your call will succeed, so there is no mandatory check built into those functions. If you want a check, you can write one yourself.
The default new is slightly different, as it incorporates facilities for calling a new_handler, and so the checking is done anyway. (Recall that an exception is only expensive if you actually throw it, so that aspect isn't so important.) If you wanted to, you could always replace your own global operator new() by one which literally just forwards the argument to malloc(). (That would of course make it unsafe to use the default new expression, as you have no way of checking now that you can construct an object at the returned pointer. So you'll end up writing a check yourself and using placement-new, which is almost exactly what the nothrow-version does.)
Return a zero pointer: for example, when doing illegal pointer downcasting (interesting, doing an illegal reference downcasting will throw a bad_cast)
dynamic_cast provides an way to check the validity of the cast. It is by no means an exception as such.With pointers the cast returns a NULL because throwing an exception would be an overhead and the same can be achieved by returning a NULL, With the restriction that References cannot be NULL, there was no option but to throw an exception, there was no other way to return the result to user in this case.
Give user a choice of whether to throw an exception, for example, new() will throw bad_alloc() when out of memory, but you can also choose (nothrow) as an option of new().
Long ago new just returned NULL as in case of malloc, but later on it was standardized to throw an bad_alloc exception, This would have meant all the code previously written using new would have to be modified to a large extent to handle the exception, to avoid this and maintain a compatibility the nothrow version of new was introduced.
Pointer downcasts returning null is a simpler and faster way to test whether a given object is of the given subclass. I.e. you can write stuff like if (dynamic_cast<A*>(v) || dynamic_cast<B*>(v)), or if (A* a = dynamtic_cast<A*>(v)) doStuffWith(a);, which would've been cumbersome with exceptions. Here you actually expect casts to fail, while exceptions are exceptional by their nature, in that they are supposed to rarely be thrown during the normal execution of your program.
In other cases explicit checks for incorrect values may be omitted just for performance reasons. C++ is supposed to be efficient, instead of attempting to prevent one from shooting himself in the leg.
Most of this depends on whether there are enough appropriate return values to express the "failure" conditions and whether those values are convenient or not.
Rationale behind cited examples
std::stack<>::pop() does not throw an error because it doesn't have an error value and it simplifies calling code. It might not be an application logic error to attempt to pop an empty stack.
std::sqrt() has an appropriate value (not a number) which was included in floating point representations precisely for this purpose. It also has the benefit of propagating cleanly through other computations.
dynamic_cast<> on pointer types returns a null pointer to indicate a failed cast because the null pointer is already a standard way to represent "points to nothing". However, there is no such equivalent for references, so it must throw an exception as the return value cannot be used to indicate an error.
In contrast, std::string::substr() can't return an empty string to represent failure as an empty string is a valid sub-string of all strings.
new throwing std::bad_alloc or not seems to have historical roots, but, like dynamic_cast<> on pointers, it might be convenient for some code that would try alternatives not to pay for exception handling.
The c++ standard library is designed to be efficient, it avoids unnecessary runtime checks when possible.
1 Contains violations on the preconditions on very small/fast methods, checking these preconditions would most likely take longer than executing the methods themselves (pop is most likely a single decrement on a stack of simple types).
2 dynamic_cast checks and casts a given pointer to a compatible type. There is no separate way of only checking if a cast is possible since it would have to do the same work as the cast. Since c++ provides no separate way to only check if the cast is possible we have to expect that it may fail and it has a good error value to use when it fails (NULL). The reference version has to throw an exception as it cannot return an error value.
3 substr guarantees an exception, this may be for two reasons. One: the substr method is quite a bit more complex and slow than the methods mentioned in 1 and therefor the overhead of checking the precondition is negligible. Two: string processing is one of the biggest contributors to security holes as you are most likely processing user input, checking for overflows or out of bounds access is necessary to keep the process secure/stable. The c-library provides fast, unchecked and insecure methods to manipulate strings for those who need the speed.
4 new has to check whether it can return an address or fail in both cases, since running out of memory is unexpected by most applications the exception is reasonable. However you can write c++ while using a small subset of its features and many projects do not use exceptions as making your code exception safe is hard (especially if you use third party libraries which are not), since new is a central part of c++ an exception free implementation becomes necessary.
Can anyone explain Exception Specifications as used in C++ ?
When are they used (I have rarely seen it used in code)
What are the pros and cons (benefits/disadvantages) of using exception specifications?
When are they used (I have rarely seen it used in code)
Hopefully never as they are deprecated in the next version of C++ due for standardization next year.
What are the pros and cons (benefits/disadvantages) of using exception specifications?
They provide a way for readers of your code to know exactly what exceptions a function is allowed to throw. The problem is, that if an unexpected exception (one not in the specification) is thrown, then the program will be terminated (by default).
They are generally regarded as a bad idea.
They say what a method will throw. The downside is that if that method throws anything else then your app terminates. So it's a guarantee but not in the same way that Java does it. And it adds the overhead of inspection.
The important thing to know is: exception specifications are deprecated in the next revision of C++, except for the no-throw specifier (throw()), which is basically officially saying "don't use them".
Putting throw() after a function means the function does not throw any exceptions. If it does anyway, the application will be terminated (probably - the unexpected handler is called), so the rest of your application can use that function knowing it will not throw an exception. This is can be handy for writing exception-safe code.
Example:
void MyFunction() throw() // does not throw any exceptions
{
/* ... */
{
They indicate to the programmer which exceptions will be thrown from that function. They have the advantage that you have the guarantee that no other exceptions can be thrown from that function. However, there is no compile-time checking of whether the function actually throws any exceptions other than what is indicated in the throw specifier. Instead, it's checked at runtime. And if it fails, then unexpected() is called, which by default calls abort() which in turn by default terminates your program. So, unless you really want your program to die if you screw up and an unexpected exception gets thrown, it's probably a bad idea to use them.
The one place where I would actually recommend using them is on destructors. It's really bad if a destructor throws. They should never throw. So, if you use throw() on a destructor to indicate that it can't throw an exception, then you know that your program will die rather than continue in the bad state that it would be in after an exception was thrown from a destructor.
Regardless, if you use any kind of throw specifier, you have to be sure that you really do want your program to die if it's violated. So, generally-speaking, it's best not to use them.
Basically, exception specifications allow the compiler to optimize the stack. The disadvantage is that it's a hell of a lot of extra spec. This means that you commonly see it in library work but not so much in working code.
I believe there's also some compile-time exception-safety thing going on, but since I've never used it, I can't be sure.
void MyFunction(int i) throw();
it just tells the compiler that the function does not throw any exceptions.
It can't make sure the function throw nothing, is that right?
So what's the use of throw()
Is it redundant? Why this idea is proposed?
First of all, when the compiler works right, it is enforced -- but at run-time, not compile-time.. A function with an empty exception specification will not throw an exception. If something happens that would create an exception escaping from it, will instead call unexpected(), which (in turn) calls abort. You can use set_unexpected to change what gets called, but about all that function is allowed to do is add extra "stuff" (e.g. cleanup) before aborting the program -- it can't return to the original execution path.
That said, at least one major compiler (VC++) parses exception specifications, but does not enforce them, though it can use empty exception specifications to improve optimization a little. In this case, an exception specification that isn't followed can/does result in undefined behavior instead of necessarily aborting the program.
It can't make sure the function throw nothing, is that right?
You are almost there. It is an exception specification. It means that as an implementer you gurantee to your client(s) that this piece of code will not throw an exception. This does not however stop some functions within MyFunction to throw and which, if you do not handle them, will bubble up and cause your/client's program in a way you did not intent it to. It does not even mean that you cannot have a throw expression inside.
It is best to avoid such specification, until and unless you are absolutely sure that your code will never throw -- which is kind of difficult except for very basic functions. See the standard swap, pointer assignments etc.
Is it redundant? Why this idea is proposed?
Not exactly. When properly used, it can be of help to the compiler for optimization purposes. See this article. This article explains the history behind no-throw well.
Digging a bit more I found this excellent article from the Boost documentation. A must read. Read about the exception guarantees part.
As you said, it just tells the compiler that the function does not throw any exceptions.
When the compiler expects possible exceptions, it often has to generate the code in some specific form, which makes it less efficient. It also might have to generate some additional "household" code for the sole purpose of handling exceptions when and if they are thrown.
When you tell the compiler that this function never throws anything, it makes it much easier to the compiler to recognize the situations when all these additional exception-related expenses are completely unnecessary, thus helping the compiler to generate more efficient code.
Note, that if at run time you actually try to throw something out of a function that is declared with throw() specification, the exception will not be allowed to leave the function. Instead a so called unexpected exception handler will be invoked, which by default will terminate the program. So, in that sense it is actually enforced that a throw() function does not throw anything.
P.S. Since exception specifications are mostly affecting the run-time behavior of the program, in general they might not have any compile time effect. However, this specific exception specification - the empty one throw() - is actually recognized by some compilers at compile time and does indeed lead to generation of more efficient code. Some people (me included) hold the opinion that the empty exception specification is the only one that is really worth using in the real-life code.
To be honest exception specifications in the real world have not turned out to be as usfull as envisoned by the origianl designers. Also the differences between C++ runtime checked exception specifications and Java's compile time checked exception specifications has caused a lot of problems.
The currently except norms for exception specifications are:
Don't use them.
Unless they are the empty form.
Make sure that if you use the empty form gurantee that you actually catch all excetions.
The main problem is that if you have a method with a throw spec. Then somthing it uses changes underneath and now throws new types of exception there is no warning or problem with the code. But at runtime if the exception occurs (the new one that is not in throw spec) then your code will terminate(). To me termination is a last resort and should never happen in a well formed program I would much rather unwind the stack all the way back to main with an exception thus allowing a sliughtly cleaner exit.