What is the difference between declaring function as __attribute__(nothrow) and `throw()` - c++

What is the difference between declaring function as __attribute__(nothrow) and throw() when using C++ compiler with support of gnu extensions (e.g. g++ itself on Linux; C++03).
As I understand, both variants are to say compiler that this function will not throw exceptions. But implementations may be different
How will compiler use this information?
What if I will throw exception while running inside the nothrow or throw() function and this exception will go up to the function? Will function pass exception further or it will hide exception or something else?

There are several differences:
The __attribute__((...)) syntax is a gnu compiler extension, which is not exactly portable, throw() is defined by the C++ standard.
If I read it correctly, __attribute__((nothrow)) tells the compiler that it can safely assume that a function won't raise an exception, and can possibly omit emitting some code necessary for exception handling (this is on the caller side). throw(), on the other hand, implicitely catches all exceptions that arise from the function in question, and terminates the program when something is caught by calling first the unexpected exception handler, which by default calls terminate() (this happens on the callee side).
In terms of programming, throw() is the much more useful, because it can safeguard your code from being silently skipped by an exception. When I work on a project that uses exceptions, I make a point to add throw() to every single function I write.
Note, however, that neither __attribute__((nothrow)) nor throw() will cause the compiler to actually check whether no exception can be thrown. This is quite unfortunate, but the C++ standard explicitely says that the compiler must not throw an error on a throw within a function declared with throw().

Related

Was there any version of C++ (even pre-standard) were `throw()` did not mean "cannot throw, ever"?

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.

g++ -fno-enforce-eh-specs - why/how does this violate the C++ standard?

From man gcc:
-fno-enforce-eh-specs
Don't generate code to check for violation of exception specifications
at run time. This option violates the C++ standard, but may be useful
for reducing code size in production builds.
When a compiler optimizes, it removes all sorts of checks, it breaks the boundaries between functions, it might even avoid things like system calls the developer put in the code in some cases. So:
Why is exception specification violation checking so special that it cannot be skipped?
What exactly is being checked?
If using this switch is so useful for reducing code size, how come the C++ standard requires these checks? I thought the idea is zero-overhead abstractions whenever possible.
The (now old?) standard requires that a function declared void f() throw(x); must not throw any exception other than x (or possibly derived from x?). If it tries to throw something else, std::unexpected() should be called, and probably end up in a call to std::terminate() to kill the program.
But if the exact type of the exception cannot be determined at compile time, a run-time check might be needed to determine if the exception is of an acceptable type.
Of course, if that check is removed by this option, an incorrect exception might escape from the function. And that would be a violation of the standard.
Why is exception specification violation checking so special that it cannot be skipped?
What exactly is being checked?
This has been answered already, but for completeness in my answer as well: for functions with throw(...) and noexcept specifications, when exceptions get thrown that are not permitted, std::unexpected() or std::terminate() must be called.
Effectively, they turn something like
void f();
void g() noexcept { f(); }
into something very similar to:
void f();
void g() { try { f(); } catch (...) { std::terminate(); } }
If using this switch is so useful for reducing code size, how come the C++ standard requires these checks? I thought the idea is zero-overhead abstractions whenever possible.
Indeed. But there is no way to implement this without overhead. Compilers do already manage to implement exceptions in such a way that the code that gets executed at run-time, as long as no exceptions are thrown, is identical to the version without exception handling. In that sense, on platforms with suitable ABIs, zero-overhead exceptions has been achieved. They, however, do still annotate that code with special markers that lets the run-time library figure out what code to call when exceptions do end up thrown. Those special markers take up space. The code that ends up interpreting those markers takes up space as well. And the actual exception handling code, even if it's only std::terminate(), takes up yet more space.

C++ throw() optimization

According to Optimizing C++,
Use the empty exception specification (that is, append throw() to the declaration) for the functions you are sure will never throw exceptions.
What if I know that 90% of my methods won't throw an exception? It seems unconventional and verbose to append throw() to all of those methods. If not, what are the advantages? Or am I misunderstanding something here?
C++11 has introduced noexcept, throw is somewhat deprecated (and according to this less efficient)
noexcept is an improved version of throw(), which is deprecated in C++11. Unlike throw(), noexcept will not call std::unexpected and may or may not unwind the stack, which potentially allows the compiler to implement noexcept without the runtime overhead of throw().
When an empty throw specification is violated, your program is terminated; this means you should only declare your functions as non throwing, only when they have a no throw exception guarantee.
Finally you need a move constructor to be non throwing (specified with noexcept) to be able to use the r-value ref version of std::vector<T>::push_back (see a better explanation here)
The standard throw() doesn't enhance optimizability.
If a method is marked as throw() then the compiler is forced to check if an exception is thrown from the method and unwind the stack - just like if the function is not marked as throw(). The only real difference is that for a function marked throw() the global unexpected_handler will be called (which generally calls terminate()) when the exception leaves the function, unwinding the stack to that level, instead of the behavior for functions without an exception specification which will handle the exception normally.
For pre-C++11 code, Sutter & Alexandrescu in "C++ Coding Standards" suggested:
Avoid exception specifications.
Take exception to these specifications: Don’t write exception
specifications on your functions unless you’re forced to (because
other code you can’t change has already introduced them; see
Exceptions).
...
A common but nevertheless incorrect belief is that exception
specifications statically guarantee that functions will throw only
listed exceptions (possibly none), and enable compiler optimizations
based on that knowledge
In fact, exception specifications actually do something slightly but
fundamentally different: They cause the compiler to inject additional
run-time overhead in the form of implicit try/catch blocks around the
function body to enforce via run-time checking that the function does
in fact emit only listed exceptions (possibly none), unless the
compiler can statically prove that the exception specification can
never be violated in which case it is free to optimize the checking
away. And exception specifications can both enable and prevent further
compiler optimizations (besides the inherent overhead already
described); for example, some compilers refuse to inline functions
that have exception specifications.
Note that in some versions of Microsoft's compilers (I'm not sure if this behavior has changed in more recent versions, but I don't think so), throw() is treated in a non-standard way. throw() is equivalent to __declspec(nothrow) which does allow the compiler to assume that the function will not have an exception thrown and undefined behavior will result if one is.
C++11 deprecates the C++98 style exception specification and introduced the noexcept keyword. Bjarne Stroustup's C++11 FAQ says this about it:
If a function declared noexcept throws (so that the exception tries to
escape, the noexcept function) the program is terminated (by a call to
terminate()). The call of terminate() cannot rely on objects being in
well-defined states (i.e. there is no guarantees that destructors have
been invoked, no guaranteed stack unwinding, and no possibility for
resuming the program as if no problem had been encountered). This is
deliberate and makes noexcept a simple, crude, and very efficient
mechanism (much more efficient than the old dynamic throw()
mechanism).
In C++11 if an exception is thrown from a function marked as noexcept the compiler is not obligated to unwind the stack at all. This affords some optimization possibilities. Scott Meyers discusses the new noexcept in his forthcoming book "Effective Modern C++".

Is it safe to use the throw() suffix on a function containing std::string?

I have a member function that doesn't throw anything so i appended the throw() suffix to the end of it, indicating that it won't throw any exceptions.
My question is, in the function I make use of several std::string, and lets say something goes wrong in the initialization of the std::string, and it throws bad_alloc or out_of_range (or what ever else can go wrong with a std::string).
Is it still safe to still add the throw() suffix?
Herb Sutter says that
exception specifications confer a lot less benefit than they're worth
It can cause more problems than bring benefits. So, you should think twise before doing that.
The exception specification makes a promise about all code which runs inside the function, whether you wrote it or not.
If std::string throws from inside your function, that promise is broken, and your program fails. (std::unexpected exception, which normally means your program terminates hard)
The throw() specification is proper only if:
Nothing your function does can throw, even indirectly
or
Your function catches all such exceptions and exits normally (no rethrow).
Two things.
First: the throw() specification add a runtime check that the function does not throw, calling std::unexpected_exception if the promise is broken, which will terminate the program.
Second: throw() is not advised, and has been deprecated in C++11. In C++11 you can use noexcept instead (or the more malleable form noexcept(boolean-expression)). No runtime check is created, and the behavior is undefined if the function throws.

about throw() in C++

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.