There are several special functions which usually guarantee not to throw excpetions, e.g.:
Destructors
swap method
Consider the following swap implementation, as stated in this answer:
friend void swap(dumb_array& first, dumb_array& second)
{
using std::swap;
swap(first.mSize, second.mSize);
swap(first.mArray, second.mArray); // What if stack overlow occurs here?
}
It uses two swap functions - for integer and for pointer. What if the second function will cause stack overflow? Objects will become corrupted. I guess it is not an std::exception, it is some kind of system exception, like Win32-exception. But now we cannot guarantee no-throwing, since we're calling a function.
But all authoritative sources just use swap like it's ok, no exceptions will ever be thrown here. Why?
In general you cannot handle running out of stack. The standard doesn't say what happens if you run out of stack, neither does it talk about what the stack is, how much is available, etc. OSes may let you control it at the time the executable is built or when it is run, all of which is fairly irrelevant if you're writing library code, since you have no control of how much stack the process has, or how much has already been used before the user calls into your library.
You can assume that stack overflow results in the OS doing something external to your program. A very simple OS might just let it go weird (undefined behavior), a serious OS might blow the process away, or if you're really unlucky it throws some implementation-defined exception. I actually don't know whether Windows offers an SEH exception for stack overflow, but if it does then it's probably best not to enable it.
If you're concerned, you can mark your swap function as noexcept. Then in a conforming implementation, any exception that tries to leave the function will cause the program to terminate(). That is to say, it fulfils the noexcept contract at the cost of taking out your program.
What if the second function will cause stack overflow?
Then your program is in an unrecoverable faulted state, and there is no practical way to handle the situation. Hopefully, the overflow has already caused a segmenation fault and terminated the program.
But now we cannot guarantee no-throwing
I've never encountered an implementation that would throw an exception in that state, and I'd be rather scared if it did.
But all authoritative sources just use swap like it's ok, no exceptions will ever be thrown here. Why?
The authoritative sources I've read (like this one, for example) don't "just use it like it's OK"; they say that if you have (for example) a non-throwing swap function, and a non-throwing destructor, then you can provide exception-safety guarantees from functions that use them.
It's useful to categorise functions according to their exception guarantees:
Basic: exceptions leave everything in a valid but unspecified state
Strong: exceptions leave the state unchanged
No-throw: no exceptions will be thrown.
Than a common approach to providing the "strong" guarantee is:
do the work that might throw on a temporary copy of the state
swap that copy with the live state (requiring a non-throwing swap operation)
destroy the old state (requiring a non-throwing destructor)
If you don't have a no-throw guarantee from those operations, then it's more difficult, and perhaps impossible, to provide a strong guarantee.
Related
I'm trying to understand the machinery behind stack unwinding in C++. In other words I'm interested in how this feature is implemented (and whether that is a part of the standard).
So, the thread executes some code until an exception is thrown. When the exception is thrown, what are the threads/interrupt handlers used to record the state and unwind the stack? What is guaranteed by the standard and what is implementation specific?
The thread executes some code until the exception is thrown, and it continues to do so. Exception handling still is C++ code.
The throw expression creates a C++ object, running in the context of the throwing function. While the constructor of the exception object is running, all objects in the scope of the throwing function are still alive.
Directly after, however, the stack unwind happens. The C++ compiler will have arranged for a return path that does not require a return object, but which does allow passing of the exception object. Just like a normal return, objects that are local to a function are being destroyed when the function returns. At binary level, this is pretty straightforward: it's just a bunch of destructor calls, and typically a stack pointer is also adjusted.
What the standard also does not specify, is the mechanism used to determine how many scopes need to be exited. The standard describes in terms of catch, but a typical CPU has no direct equivalent. Hence, this is commonly part of the C++ ABI for a given platform so that compilers sharing a ABI agree. ABI compatibility requires that a caller must catch the exceptions from a callee, even if they've been compiled with different compilers. And obviously, destructors have to be called, so the ABI also needs to arrange that mechanism. The intermediate functions could even have been compiled by a third compiler - as long as they share an ABI, it's all supposed to work.
As noted in the comments, C++ has no notion of interrupts. If the OS needs something to happen with interrupts, the compiler needs to take care of that. It matters little what exactly the C++ code is doing at that time.
For STL containers (so far, std::vector<> and std::deque<>), I'm looking for documentation that says exactly when they throw exceptions. Something like, "It throws X in situation A. It throws Y in situation B. It throws no other exceptions under any circumstances."
I'd like to reassure my exception-phobic colleagues that we know exactly what can trigger exceptions in the STL classes we use.
The most accurate information will come from the C++ standard matching your compiler, and compiler documentation. However, the spec costs money. If you're willing to settle for a few typos, the draft C++11 specification can be found here: http://open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf for free, and the latest publicly available draft (preparing for C++14) seems to be http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf.
The number 1 used container is vector, so lets go over that.
Technically the only vector member that throws an exception is at, if given an out of range index. (tada! we're done!)
Less technically, vector assign/insert/emplace/reserve/resize/push_back/emplace_back/shrink_to_fit/etc can cause a resize, which uses std::allocator<T>:allocate, which can throw std::bad_alloc in theory. In weird situations with weird allocators, swap can also trigger this too. On some systems (Linux), this pretty much never happens, because it only throws if it runs out of virtual memory, and often the program will run out of physical memory first, and the OS will simply kill the whole program. That happens regardless of exceptions though, so this doesn't count against C++ exceptions.
Probably relevant is that the elements in a vector can throw any exception when copied, which affects constructors, assignment, insert/emplace/push_back/emplace_back, reserve, resize/shrink_to_fit. (If your element has a noexcept move constructor and move assignment, and it really really really should, then happens only when copying the entire vector).
The spec details exactly what exceptions are thrown and often also specifies under exactly what conditions they're thrown.
The C++ standard documents when exceptions will be thrown and under what circumstances for the standard library containers. There are also general rules about which methods will not throw exceptions for containers.
Alternatively, you can search the headers for throw (or the equivalent macro) to determine under what circumstances exceptions will trigger.
Today I learned that swap is not allowed to throw an exception in C++.
I also know that the following cannot throw exceptions either:
Destructors
Reading/writing primitive types
Are there any others?
Or perhaps, is there some sort of list that mentions everything that may not throw?
(Something more succinct than the standard itself, obviously.)
There is a great difference between cannot and should not. Operations on primitive types cannot throw, as many functions and member functions, including many operations in the standard library and/or many other libraries.
Now on the should not, you can include destructors and swap. Depending on how you implement them, they can actually throw, but you should avoid having destructors that throw, and in the case of swap, providing a swap operation with the no-throw guarantee is the simplest way of achieving the strong exception guarantee in your class, as you can copy aside, perform the operation on the copy, and then swap with the original.
But note that the language allows both destructors and swap to throw. swap can throw, in the simplest case if you do not overload it, then std::swap performs a copy construction, an assignment and a destruction, three operations that can each throw an exception (depending on your types).
The rules for destructors have changed in C++11, which means that a destructor without exception specification has an implicit noexcept specification which in turn means that if it threw an exception the runtime will call terminate, but you can change the exception specification to noexcept(false) and then the destructor can also throw.
At the end of the day, you cannot provide exception guarantees without understanding your code base, because pretty much every function in C++ is allowed to throw.
So this doesn't perfectly answer you question -- I searched for a bit out of my own curiosity -- but I believe that nothrow guaranteed functions/operators mostly originate from any C-style functions available in C++ as well as a few functions which are arbitrarily simple enough to give such a guarantee. In general it's not expected for C++ programs to provide this guarantee ( When should std::nothrow be used? ) and it's not even clear if such a guarantee buys you anything useful in code that makes regular use of exceptions. I could not find a comprehensive list of ALL C++ functions that are nothrow functions (please correct me if I missed a standard dictating this) other than listings of swap, destructors, and primitive manipulations. Also it seems fairly rare for a function that isn't fully defined in a library to require the user to implement a nothrows function.
So perhaps to get to the root of your question, you should mostly assume that anything can throw in C++ and take it as a simplification when you find something that absolutely cannot throw an exception. Writing exception safe code is much like writing bug free code -- it's harder than it sounds and honestly is oftentimes not worth the effort. Additionally there are many levels between exception unsafe code and strong nothrow functions. See this awesome answer about writing exception safe code as verification for these points: Do you (really) write exception safe code?. There's more information about exception safety at the boost site http://www.boost.org/community/exception_safety.html.
For code development, I've heard mixed opinions from Professors and coding experts on what should and shouldn't throw an exception and what guarantees such code should provide. But a fairly consistent assertion is that code which can easily throw an exception should be very clearly documented as such or indicate the thrown capability in the function definition (not always applicable to C++ alone). Functions that can possible throw an exception are much more common than functions that Never throw and knowing what exceptions can occur is very important. But guaranteeing that a function which divides one input by another will never throws a divide-by-0 exception can be quite unnecessary/unwanted. Thus nothrow can be reassuring, but not necessary or always useful for safe code execution.
In response to comments on the original question:
People will sometimes state that exception throwing constructors are evil when throw in containers or in general and that two-step initialization and is_valid checks should always be used. However, if a constructor fails it's oftentimes unfixable or in a uniquely bad state, otherwise the constructor would have resolved the problem in the first place. Checking if the object is valid is as difficult as putting a try catch block around initialization code for objects you know have a decent chance of throwing an exception. So which is correct? Usually whichever was used in the rest of the code base, or your personal preference. I prefer exception based code as it gives me a feeling of more flexibility without a ton of baggage code of checking every object for validity (others might disagree).
Where does this leave you original question and the extensions listed in the comments? Well, from the sources provided and my own experience worrying about nothrow functions in an "Exception Safety" perspective of C++ is oftentimes the wrong approach to handling code development. Instead keep in mind the functions you know might reasonably throw an exception and handle those cases appropriately. This is usually involving IO operations where you don't have full control over what would trigger the exception. If you get an exception that you never expected or didn't think possible, then you have a bug in your logic (or your assumptions about the function uses) and you'll need to fix the source code to adapt. Trying to make guarantees about code that is non-trivial (and sometimes even then) is like saying a sever will never crash -- it might be very stable, but you'll probably not be 100% sure.
If you want the in-exhaustive-detail answer to this question go to http://exceptionsafecode.com/ and either watch the 85 min video that covers just C++03 or the three hour (in two parts) video that covers both C++03 and C++11.
When writing Exception-Safe code, we assume all functions throw, unless we know different.
In short,
*) Fundamental types (including arrays of and pointers to) can be assigned to and from and used with operations that don't involve user defined operators (math using only fundamental integers and floating point values for example). Note that division by zero (or any expression whose result is not mathematically defined) is undefined behavior and may or may not throw depending on the implementation.
*) Destructors: There is nothing conceptually wrong with destructors that emit exceptions, nor does the standard prohibited them. However, good coding guidelines usually prohibit them because the language doesn't support this scenario very well. (For example, if destructors of objects in STL containers throw, the behavior is undefined.)
*) Using swap() is an important technique for providing the strong exception guarantee, but only if swap() is non-throwing. In general, we can't assume that swap() is non-throwing, but the video covers how to create a non-throwing swap for your User-Defined Types in both C++03 and C++11.
*) C++11 introduces move semantics and move operations. In C++11, swap() is implemented using move semantics and the situation with move operations is similar to the situation with swap(). We cannot assume that move operations do not throw, but we can generally create non-throwing move operations for the User-Defined Types that we create (and they are provided for standard library types). If we provide non-throwing move operations in C++11, we get non-throwing swap() for free, but we may choose to implement our own swap() any way for performance purposes. Again, this is cover in detail in the video.
*) C++11 introduces the noexcept operator and function decorator. (The "throw ()" specification from Classic C++ is now deprecated.) It also provides for function introspection so that code can be written to handle situations differently depending on whether or not non-throwing operations exist.
In addition to the videos, the exceptionsafecode.com website has a bibliography of books and articles about exceptions which needs to be updated for C++11.
The strong exception safety guarantee says that an operation won't change any program state if an exception occurs. An elegant way of implementing exception-safe copy-assignment is the copy-and-swap idiom.
My questions are:
Would it be overkill to use copy-and-swap for every mutating operation of a class that mutates non-primitive types?
Is performance really a fair trade for strong exception-safety?
For example:
class A
{
public:
void increment()
{
// Copy
A tmp(*this);
// Perform throwing operations on the copy
++(tmp.x);
tmp.x.crazyStuff();
// Now that the operation is done sans exceptions,
// change program state
swap(tmp);
}
int setSomeProperty(int q)
{
A tmp(*this);
tmp.y.setProperty("q", q);
int rc = tmp.x.otherCrazyStuff();
swap(tmp);
return rc;
}
//
// And many others similarly
//
void swap(const A &a)
{
// Non-throwing swap
}
private:
SomeClass x;
OtherClass y;
};
You should always aim for the basic exception guarantee: make sure that in the event of an exception, all resources are released correctly and the object is in a valid state (which can be undefined, but valid).
The strong exception guarantee (ie. "transactions") is something you should implement when you think it makes sense: you don't always need transactional behavior.
If it is easy to achieve transactional operations (eg. via copy&swap), then do it. But sometimes it is not, or it incurs a big perfomance impact, even for fundamental things like assignment operators. I remember implementing something like boost::variant where I could not always provide the strong guarantee in the copy assignment.
One tremendous difficulty you'll encounter is with move semantics. You do want transactions when moving, because otherwise you lose the moved object. However, you cannot always provide the strong guarantee: think about std::pair<movable_nothrow, copyable> (and see the comments). This is where you have to become a noexcept virtuoso, and use an uncomfortable amount of metaprogramming. C++ is difficult to master precisely because of exception safety.
As all matters of engineering, it is about balance.
Certainly, const-ness/immutability and strong guarantees increase confidence in one's code (especially accompanied with tests). They also help trim down the space of possible explanations for a bug.
However, they might have an impact on performance.
Like all performance issues, I would say: profile and get rid of the hot spots. Copy And Swap is certainly not the only way to achieve transactional semantics (it is just the easiest), so profiling will tell you where you should absolutely not use it, and you will have to find alternatives.
It depends on what environment your application is going to run in. If you just run it on your own machine (one end of the spectrum), it might not be worth to be too strict on exception safety. If you are writing a program e.g. for medical devices (the other end), you do not want unintentional side-effects left behind when an exception occurs. Anything in-between is dependent on the level of tolerance for errors and available resources for development (time, money, etc.)
Yes, the problem you are facing is that this idiom is very hard to scale. None of the other answers mentioned it, but another very interesting idiom invented by Alexandrescu called scopeGuards. It helps to enhance the economy of the code and makes huge improvements in readability of functions that need to conform to strong exception safety guarantees.
The idea of a scope guard is a stack instance that lets just attach rollback function objects to each resource adquisition. when the scope guard is destructed (by an exception) the rollback is invoked. You need to explicitly call commit() in normal flow to avoid the rollback invocation at scope exit.
Check this recent question from me that is related to designed a safe scopeguard using c++11 features.
Why does std::stack::pop() not throw an exception if the stack is empty and there is nothing to pop?
(I'm designing a specialized Stack for my own code and would like to know the tradeoffs with this approach (which requires one to manually check if the stack is empty) vs. throwing an exception.
My guess here would be that although C++ supports exception-handling, it comes with a small runtime overhead, and therefore, for maximum performance, the decision was made not to throw an exception in std::stack::pop).
I would argue that the reason pop() doesn't have to throw an exception has nothing to do with efficiency or performance, but with - exceptions.
As is argued elsewhere:
SGI explanation: http://www.sgi.com/tech/stl/stack.html
One might wonder why pop() returns
void, instead of value_type. That is,
why must one use top() and pop() to
examine and remove the top element,
instead of combining the two in a
single member function? In fact, there
is a good reason for this design. If
pop() returned the top element, it
would have to return by value rather
than by reference: return by reference
would create a dangling pointer.
Return by value, however, is
inefficient: it involves at least one
redundant copy constructor call. Since
it is impossible for pop() to return a
value in such a way as to be both
efficient and correct, it is more
sensible for it to return no value at
all and to require clients to use
top() to inspect the value at the top
of the stack.
std::stack < T > is a template. If pop() returned the top element, it
would have to return by value rather
than by reference as per the of above
explanation. That means, at the caller
side it must be copied in an another T
type of object. That involves a copy
constructor or copy assignment
operator call. What if this type T is
sophisticated enough and it throws an
exception during copy construction or
copy assignment? In that case, the
rvalue, i.e. the stack top (returned
by value) is simply lost and there is
no other way to retrieve it from the
stack as the stack's pop operation is
successfully completed!
Once we conclude that pop should not return the element it pops and thus its interface is fixed as void pop(), it - this being my opinion - doesn't make any sense anymore to prescribe what happens when pop() is called on an empty stack.
Note that the standard requires !empty()as precondition for calling pop().
UncleBens (in the comments) certainly has a point that not checking preconditions at runtime (which is never prescribed by the C++ std AFAIK) has a certain performance smell to it. However, to quote part of the original question: (emphasis mine)
(I'm designing a specialized Stack for
my own code and would like to know the
tradeoffs with this approach (which
requires one to manually check if the
stack is empty) vs. throwing an
exception.
I will argue, that the fact that pop() doesn't return anything renders the question moot. It (IMHO) simply doesn't make sense to force pop() to validate if the stack is empty, when we really don't get anything back from it (i.e. if the stack would be empty pop() can simply be a noop, which is (admittedly) not prescribed by the Std either).
I think one can either ask why top() does not throw an exception or one can ask why pop() doesn't return the top element. If pop doesn't return anything, throwing an exception doesn't make sense (in the C++ world) -- Claiming that it doesn't throw an exception "because of the runtime costs of exceptions" like other answers seem to imply is - IMHO - missing the point.
You are correct. The C++ standard always prefers performance to safety. But there may be STL implementations that include debug range checks.
As almost all features in C++, they are designed around the concept that you don't pay for what you don't use. Not all environments support exceptions, traditionally, and most notably game development.
So forcing the use of exceptions if you use std::stack would be failing one of the design guidelines. You want to be able to use stack even if exceptions are disabled.
I think it's worth mentioning that pop() is allowed to throw if the stack is empty -- it's just not required to. In your stack, you could assert that the stack wasn't empty, and that would be perfectly fine (pop on an empty stack seems to give UB, so you can do pretty much whatever you want, really).
exceptions are optional, and the STL wants to be available everywhere. think embedded systems: lots of C++ code, no exception support from runtimes.
Performance aside, I don't think popping from an empty stack is an exceptional scenario - therefore I would't throw there either.