Recently in my code I have been explicitly writing noexcept(false) on functions that I know do throw exceptions, mainly for people reading the code. However, I am wondering if this affects the behavior of my code or the way the compiler interprets it. Does it make any difference?
Note: I am aware that destructors are implicitly noexcept and that you have to specify noexcept(false) to change that, I am wondering about other functions.
Having no exception-specifier and explicitly stating noexcept(false) are equivalent, see ยง15.4/12:
A function with no exception-specification or with an exception-specification of the form noexcept(constant-expression) where the constant-expression yields false allows all exceptions.
So the compiler should not distinguish between them when considering exceptions.
More importantly, there's no need for you to be tacking on noexcept(false) to your functions. As a C++ developer, you should assume every function throws by default (which is why the standard takes this stance), so you're adding no new information by writing it out; it's a waste of time for everyone.
Rather, do mark the special case where a function definitely does not throw with noexcept, and do mark the cases where a function may throw depending on some condition with noexcept(condition).
If your function is purposefully the source of some exception E, write that in your documentation.
The one case I can think of is on a destructor. I know you should never throw in a destructor. But in some cases you are stuck with code that does this and have no work around.
Since c++ automagically adds noexcept to destructors, this is the only way to undo it and prevent app terminate when the code throws.
https://github.com/chriskohlhoff/asio/issues/1216
from: https://akrzemi1.wordpress.com/2011/09/21/destructors-that-throw/
The compiler will still invisibly add specification noexcept to your
destructor. And this means that the moment your destructor throws an
exception, std::terminate will be called, even if there was no
double-exception situation. If you are really determined to allow your
destructors to throw, you will have to specify this explicitly; you
have three options:
Explicitly specify your destructor as noexcept(false),
Inherit your class from another one that already specifies its destructor as noexcept(false).
Put a non-static data member in your class that already specifies its destructor as noexcept(false).
In his book More Exceptional C++, Herb Sutter has the following snippet (pp. 130):
The right answer to the Example 19-1 is much simpler:
// Example 19-4: The right solution
//
T::~T() /* throw() */
{
// ... code that won't throw ...
}
Example 19-4 demonstrates how to make a design decision instead of waffling.
Note that the throw() throws-nothing exception specification
is only a comment. That's the style I've chosen to follow, in part
because it turns out that exception specifications confer a lot less
benefit than they're worth. Whether or not you decide to actually write the specification is a matter of taste.
(emphasis mine)
So, I feel I must point out that one of the leading experts in C++ exception-safe code seems to be against the whole concept of adding exception specifications for the compiler to use (but still leaving it in the code for the programmers to understand).
Just thought it may be interesting info...
Related
When should one add the noexcept attribute to a function? i.e. when is the compiler not able to tell a function throws? Should everything be marked or is there a way to tell?
I'm not a fan of premature optimization, and I'm not a fan of premature attribution. I don't know of a way to "profile" the need of noexcept the same way I profile performance when optimizing.
When evaluating where it is necessary, please comment on the most common compilers, e.g. MSVC, GCC, etc.
The C++ Core Guidelines recommends basically use it everywhere that the code doesn't throw. This is mostly important for libraries because code checkers use the functions you call to see if it's noexcept, otherwise you get a cascade of warnings.
That said, the most important recommendations are to make swap, move, and destructors noexcept.
The C++ Core Guidelines also recommends making default constructors noexcept which is great in general, but many patterns (like the pImpl idiom) often allocate memory in their default constructor. Therefore, I generally use noexcept on default constructors (or constructors that only take defaulted parameters), but if I know it can throw I make a point of explicitly marking it nothrow(false).
If you declare a default constructor, copy constructor, assignment operator, move constructor, move operator, or destructor to be =default it's implicitly noexcept. All destructors are also implicitly noexcept.
There's a notion that you can mark something noexcept to mean "if this does throw, go ahead and crash". I find this notion a bit wooly so in my code I mark things that can throw noexcept(false) or leave it unspecified. That's usually stuff that calls new or initializes std containers.
When should one add the noexcept attribute to a function?
Whenever you want to document and enforce that a function never throws.
It is important to recall that a mistake here means there will be a call to std::terminate() instead of propagating the exception. Due to this, it can be a pessimization.
i.e. when is the compiler not able to tell a function throws?
It is the opposite: the compiler has to assume everything throws unless it can prove otherwise (or is told otherwise).
It will be able to prove it when it has the required definitions. For instance, between TUs without LTO, it won't.
I don't know of a way to "profile" the need of noexcept
Like in any other case: you measure with and without.
For most projects, working on enabling LTO is a better way to deal with it.
The questions is about history of C++: ISO standards, revised standards (with DR), even draft standards; all count as "a C++".
Is there any C++ where this property does not hold:
A function declared with an empty throw-specification throw() cannot throw an exception.
I'd like a counter example if that property does not hold.
Comments:
It goes without saying that throwing, then catching (without rethrowing) an exception inside a function, does that turn it info "a function throwing an exception". A function throwing an exception, according to its specification, throws at its caller. (If you do stuff internally it isn't part of the specification by definition.)
[Let's say that longjmp is forbidden as we have destructible objects.]
Others equivalent expressions of that question are:
Was there ever any case where the caller of a declared no-throw function had to worry about the possibility (equivalent properties):
of that function giving back control to its caller but not with a return statement
of seeing (and being able to catch) an exception thrown by that function
of having stack unwinding caused by the call of that function
of the caller not being non throwing if all other actions (other than calling that function) are non throwing
In other words, was there any C++ where the compiler could not optimize the calling function based on seeing a no-throw declaration of a called function?
C++17 has deprecated throw as a function annotation, mostly. It still allows throw() and considers it equivalent to noexcept(true). That means that throw() is an indication that a function is not supposed to exit because of an exception. And violating the noexcept(true) guarantee results in undefined behavior.
The semantics of throw() before C++17 were distinct and different. It used to be promised that a call to ::std::unexpected() would happen if the throw() clause was violated (i.e. an exception was thrown and resulted in the function exiting).
So, that means that before C++17 a compiler still needed to have some mechanism for detecting that a function did not exit from an exception, even if it was annotated with throw(). This is one of the reasons that the throw(...) function annotation (with stuff between the parenthesis) was deprecated because it would make no sense to have throw() to change to be equivalent to noexcept(true) without removing the other uses that the throw annotation had.
This code in compiler explorer demonstrates the 'unexpected exception' handler. If you change the standard requested to C++17, you'll see the code for that go away.
extern void a_different_function();
void test_function() throw ()
{
a_different_function();
}
In other words, was there any C++ where the compiler could not optimize the calling function based on seeing a no-throw declaration of a called function?
The answer to this direct question is no. But that alone is highly misleading.
A compiler's ability to do any kind of optimization on a a function which happens to call some other function that has a throw() declaration is extremely limited. The only real thing a compiler could do is eliminate the emission of any code dealing with exceptions in a caller function. But because of the nature of said code, it would really only be applicable if every function it calls does not throw. That's pretty much it as far as compiler optimizations of a function that calls a throw() function is concerned.
People often talk today about how noexcept enables optimizations. And that is true; judicious use of noexcept can cause code that operates on such functions to become more efficient. But it is important to remember that using noexcept does not enable compiler optimizations; it enables user-code optimizations.
Let's take the classic case of vector<T> for a T with noexcept move support. That case is not faster because the compiler sees what would otherwise be a series of copies and automatically changes them to moves just because the move constructor is noexcept. That isn't even possible for a compiler to do; it isn't allowed to rearrange your code like that, since this would be a detectable change depending on what your copy/move constructors do.
Such cases get faster because the source-code implementation of vector detects that T is nothrow-moveable. Having detected that case, it will then invoke a completely different codepath for shuffling elements of the vector around. The code calling the non-throwing function became faster because the calling code optimized itself, not because the compiler detected anything.
To put it simply, compiler optimization of the calling function was never really the point of throw() declarations.
I want to document that function throws exception
Are those samples below equivalent?
What is the preferred way?
void validate_input(const std::string &on) throw(...)
void validate_input(const std::string &on) noexcept(false)
// throws std::runtime_error if input is invalid
void validate_input(const std::string &on)
The third one.
You should definitely write a comment explaining what exceptions the function may throw, and what that means when it does.
Otherwise, people using your function have to examine its implementation and work it out for themselves. Every time. Not good!
Put the comment alongside the ones you already have (right??) listing preconditions and postconditions and explaining what the function does.
Are those samples below equivalent?
throw(...) is different from the two others, is deprecated and going to be removed in a future standard.
Second and third are mutually equivalent (exceptions apply 1) as far as the language is concerned. Lack of exception specification implies that the function may throw (also 1).
Documenting what exceptions are thrown and in which situations is a good practice.
1 Deallocation functions and destructors are implicitly non-throwing but can be explicitly specified otherwise. Implicitly generated or defaulted special member functions etc. may "inherit" specification from base / members i.e. they are implicitly non-throwing unless a base or a member is potentially throwing.
In C++11, a destructor without any exception specification is implicitly declared with noexcept, which is a change from C++03. Therefore, a code which used to throw from destructors in C++03 would still compile fine in C++11, but will crash at runtime once it attempts throwing from such a destructor.
Since there's no compile-time error with such a code, how could it be safely transitioned to C++11, short of declaring all and every existing destructor in the code base as being noexcept(false), which would be really over-verbose and intrusive, or inspecting each and every destructor for being potentially throwing, which would be really time-consuming and error-prone to do, or catching and fixing all the crashes at runtime, which would never guarantee that all such cases are found?
Note that the rules are not actually that brutal. The destructor will only be implicitly noexcept if an implicitly declared destructor would be. Therefore, marking at least one base class or member type as noexcept (false) will poison the noexceptness of the whole hierarchy / aggregate.
#include <type_traits>
struct bad_guy
{
~bad_guy() noexcept(false) { throw -1; }
};
static_assert(!std::is_nothrow_destructible<bad_guy>::value,
"It was declared like that");
struct composing
{
bad_guy member;
};
static_assert(!std::is_nothrow_destructible<composing>::value,
"The implicity declared d'tor is not noexcept if a member's"
" d'tor is not");
struct inheriting : bad_guy
{
~inheriting() { }
};
static_assert(!std::is_nothrow_destructible<inheriting>::value,
"The d'tor is not implicitly noexcept if an implicitly"
" declared d'tor wouldn't be. An implicitly declared d'tor"
" is not noexcept if a base d'tor is not.");
struct problematic
{
~problematic() { bad_guy {}; }
};
static_assert(std::is_nothrow_destructible<problematic>::value,
"This is the (only) case you'll have to look for.");
Nevertheless, I agree with Chris Beck that you should get rid of your throwing destructors sooner or later. They can also make your C++98 program explode at the most inconvenient times.
As 5gon12eder have mentioned, there are certain rules which result in a destructor without an exception specification to be implicitly declared as either noexcept or noexcept(false). If your destructor may throw and you leave it up to the compiler to decide its exception specification, you would be playing a roulette, because you are relying on the compiler's decision influenced by the ancestors and members of the class, and their ancestors and members recursively, which is too complex to track and is subject to change during the evolution of your code. Therefore, when defining a destructor with a body which may throw, and no exception specification, it must be explicitly declared as noexcept(false). On the other hand, if you are certain that the body may not throw, you may want to declare it noexcept to be more explicit and help the compiler optimize, but be careful if you choose to do this, because if a destructor of any member/ancestor of your class decides to throw, your code will abort at runtime.
Note that any implicitly defined destructors or destructors with empty bodies pose no problems. They are only implicitly noexcept if all destructors of all members and ancestors are noexcept as well.
The best way to proceed with the transition is therefore to find all destructors with non-empty bodies and no exception specifications and declare every one of them which may throw with noexcept(false). Note that you only need to check the body of the destructor - any immediate throws it does or any throws done by the functions it calls, recursively. There's no need to check destructors with empty bodies, destructors with an existing exception specification, or any implicitly defined destructors. In practice, there would not be that many of those left to be checked, as the prevalent use for those is simply freeing resources.
Since I'm answering to myself, that's exactly what I ended up doing in my case and it was not that painful after all.
I went through this same dilemma myself once.
Basically what I concluded is that, accepting the fact that those destructors are throwing and just living with the consequences of that is usually much worse than going through the pain of making them not throw.
The reason is that you risk even more volatile and unpredictable states when you have throwing destructors.
As an example, I worked on a project once where, for various reasons, some of the developers were using exceptions for flow control in some part of the project, and it was working fine for years. Later, someone noticed that in a different part of the project, sometimes the client was failing to send some network messages that it should send, so they made an RAII object which would send the messages in its destructor. Sometimes the networking would throw an exception, so this RAII destructor would throw, but who cares right? It has no memory to clean up so its not a leak.
And this would work fine for 99% of the time, except when the exception flow control path happened to cross the networking, which then also throws an exception. And then, you have two live exceptions being unwound at once, so "bang you're dead", in the immortal words of C++ FAQ.
Honestly I would much rather have the program terminate instantly when a destructor throws, so we can have a talk with who wrote the throwing destructor, than try to maintain a program with intentionally throwing destructors, and that's the consensus of the committee / community it seems. So they made this breaking change to help you assert that your destructors are being good and not throwing. It may be a lot of work if your legacy code base has lots of hacks in it but if you want to keep developing it and maintaining it, at least on C++11 standard, you are likely better off to do the work of cleaning up the destructors.
Bottom Line:
You are right, you can't really hope to guarantee that you find all possible instances of a throwing destructor. So there will probably be some scenarios where when your code compiles at C++11, it will crash in cases that it wouldn't under C++98 standard. But on the whole, cleaning up the destructors and running as C++11 is probably going to be a whole lot more stable than just going with the throwing destructors on old standard.
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.