I have 2 questions about non-throwing functions:
Why make a function non-throwing?
How to make a function non-throwing? If the code inside the function actually may throw, then should I still make it non-throwing?
Here is an example:
void swap(Type t1, Type t2) throw()
{
//swap
}
If the code in swap won't throw at all, should I still append throw()? Why?
throw() (or noexcept in C++11) is useful for two reasons:
It allows the compiler to be more aggressive in its optimisations.
It tells function users that they can use this function in their own non-throwing functions.
Non-throwing functions are very important for writing exception safe code. For instance, the usual way of writing an exception safe operator= is via a non-throwing swap() function.
On the other hand, other exception specifications are useless and have been justly deprecated in the current standard. They don't mix well at all with templates and are too expensive to enforce.
Now, if you use a noexcept specification in a function that might actually throw, all bets are off. Even if your compiler does not terminate the program when an exception leaves the function (VS does not do it for runtime efficiency reasons, for instance), your code might not do what you thought because of optimisations. For example:
void f() noexcept
{
a();
b();
}
If a() actually throws and b() has side effects, the function behaviour will be unpredictable, because your compiler may decide to execute b() before a(), since you have told it that no exceptions will be thrown.
EDIT: Now for the second part of your question: how to make a function non-throwing?
First you need to ask yourself whether your function should really be non-throwing. For instance:
class C
{
C* CreateInstance()
{
return new C();
}
}
Since operator new can throw a std::bad_alloc, CreateInstance() can throw. You could try to avoid it with a try-catch block, handling or swallowing any exceptions that may be thrown inside the try block, but would that really be sensible? For instance:
C* CreateInstance()
{
try
{
return new C();
}
catch (...)
{
return null;
}
}
Problem solved, it seems, but would your callers be prepared for CreateInstance() returning null? If not, a crash will ensue when they try to use that pointer. Besides, a std::bad_alloc usually means that you have run out of memory and you would just be postponing the problem.
So be careful: some functions can be made non-throwing, but others should be allowed to throw. Exception safety is not a trivial matter.
Why make a function non-throwing?
So callers of the function can call it without having to take any actions to deal with exceptions being raised by the function.
How to make a function non-throwing? If the code inside the function actually may throw, then should I still make it non-throwing?
You can make the code non-throwing by putting all code which could throw the inside a try block, and deal with any exceptions without re-throwing.
void swap(T t1, T t2) noexcept {
try {
// ....
} catch (const std::exception& ex) {
// ....
} catch (...) {
// ....
}
}
If you claim your function doesn't throw, then you have to make it non-throwing. But this doesn't mean adding an exception specification, which you shouldn't do anyway, since it is deprecated. It means you must ensure the function doesn't throw, no matter what. The C++11 keyword noexcept gives you some compile-time safety in this respect.
Related
Consider this:
#include <stdexcept>
template <class T>
void F(T &&t) {
try {
t();
} catch(...) {}
}
int main() {
F([]() noexcept {}); // Call 1
F([]{}); // Call 2
F([]{ throw std::exception{}; });// Call 3
}
I found on clang++-6.0 with flags -std=c++17, regardless of the optimization flags I gave, there is always no __gxx_personality and any exception handling code for Call 1.
Can such optimization be relied on when using a different compiler? I only consider C++11 and above.
noexcept specifier was added to c++11 as a replacement for throw(). It guarantees that the function will not throw. The difference between it and throw() is that with noexcept, if the function actually throws, the stack only maybe gets unwinded, which was not the case with the former one (stack always gets unwinded). This enables more optimizations, such as completely omitting the exception handling.
To summarize, it's up to compiler when it decides to omit the exception handling, but with noexcept it has no reason to not do so, which was really hard to determinate in other case.
In P0012R1, "Make exception specifications be part of the type system",
I see that noexcept is now becoming a part of the function type.
I can't tell whether this will prevent noexcept(true) functions from still being able to call noexcept(false) functions.
Will the following code still be valid for C++17?
void will_throw() noexcept(false){
throw 0;
}
void will_not_throw() noexcept(true){
will_throw();
}
According to cppreference:
Note that a noexcept specification on a function is not a compile-time
check; it is merely a method for a programmer to inform the compiler
whether or not a function should throw exceptions.
So the syntax of your code is valid, but std::terminate will be called when executed.
Unfortunately it is valid at compile time.
Although noexcept is used by the compiler to optimize the exception handling code, making the code more performant, it's a shame they didn't push it further to give noexcept a semantic meaning.
Ideally, when you mark a method as noexcept it should also mean that the method is not supposed to let any exceptions bubble up. So if you have a method marked as noexcept but it calls other methods that are not marked as noexcept, that should give you a compile error, unless there is a try/catch block surrounding anything that can throw.
Simply calling std::terminate is a very poor language design choice, because it doesn't put any responsibility at the hands of whoever writes the noexcept method. On the contrary, it harms software reuse by making it impossible even to the consumer to work the problem around.
For example, say that I am a bad library developer and I wrote the following code:
Header file Foo.h that ships with my library:
class Foo
{
public:
void DoSomething() noexcept;
};
You are happy consumer of FooLib writing a Bar application:
Bar.cpp
#include "Foo.h"
int main()
{
Foo foo;
try
{
foo.DoSomething();
}
catch (...)
{
std::cout << "Yay!" << std::endl;
}
return 0;
}
That code compiles fine and runs fine until you have Foo throwing an exception... And it doesn't make any difference if you enclose the call to foo.DoSomething() with a try/catch block. The code will simply abort.
If you don't have the code of Foo, you can't fix it. The only solution in this case is to throw away Foo library and write your own.
The contents of Foo.cpp can be something like this:
static void PotentiallyThrowException()
{
throw 0;
}
void Foo::DoSomething() noexcept
{
PotentiallyThrowException();
}
Note that it's up to the implementer of Foo::DoSomething() to wrap their own calls into try/catch. But due to the same issue, if they are calling other methods that are marked as noexcept and those developers didn't do the same, now it's Foo::DoSomething() that is hosed. And so on, and so forth.
We can safely say that from the semantic point of view noexcept is not only useless, but it's also harmful.
noexcept(true) functions can call noexcept(false) functions. There will be a runtime error if an exception is thrown. The canonical example of why this is allowed is:
double hypotenuse(double opposite, double adjacent) noexcept(true)
{
return std::sqrt(opposite*opposite + adjacent*adjacent);
}
std::sqrt will throw domain_error if its argument is negative, but clearly that will never happen here.
(In an ideal world, it would be forbidden by default with an exception_cast to allow it where required. The result could either be UB if an exception is thrown, or std::terminate).
Including the exception specification in the function type is orthogonal to whether a function can call another function with an incompatible exception specification (without handling the exceptions that were not included in its exception specification). The former is about type safety with respect to function pointers (so that you cannot call a throwing function through a function pointer that was known not to throw). Regarding the latter, we can either prohibit it during compilation (as in Java), or treat it as a runtime error (leading to the termination of the program, as is chosen for the C++ current standard).
One may argue by brining the analogy of calling a non-const (non-static) member function from a const (non-static) member function. However the difference is that indirectly modifying an object inside a non-const member function called through a const member function would go undetected (or else would be too costly to detect) and may lead to nasty bugs, that's why it has to be prevented during compilation. Whereas the act of throwing an exception is (should be) an exceptional event and we can afford inserting run-time checks of whether the exception complies with the exception specification and should be let out, or it violates the program logic and should instead terminate the program.
Lets say I have a constructor like so
Something(SomethingElse) noexcept : member{SomethingElse, something_that_might_throw()} {
...
}
Is a noexcept okay in this case if the construction of member can throw? In the above example the member variable member is of a type I do not know.
On a side note: Are there other edge cases one needs to worry about when using noexcept?
#UPDATE:(Based on your edit): The original answer applies to everything within the block-scope of the function (constructors inclusive, including constructor-initialization-list). Why don't you try the code and see. :-)
#Original Answer
Something(SomethingElse) : member{SomethingElse} noexcept {
...
}
Your code would not compile that way. noexcept comes before the colon :
Something(SomethingElse) noexcept : member{SomethingElse} {
...
}
To your question:
Is a noexcept okay in this case if the member class constructor can
throw?
No, it's not okay. The noexcept specifier is a promise that an exception will not leave that function or constructor. Should it leave, the runtime will terminate your program.
If a search for a matching exception handler leaves a function marked
noexcept or noexcept(true), std::terminate is called immediately.
This applies to the constructor.
Despite the try..catch block, the code below gets terminated:
struct Base {
Base(){}
Base(int){ throw int(5); }
};
struct Derived : public Base {
Derived(int a) noexcept : Base(a) {}
};
int main()
{
try{
Derived d(45);
} catch(...) {}
return 0;
}
Output:
terminate called after throwing an instance of 'int'
bash: line 7: 7454 Aborted (core dumped) ./a.out
See it Live on Coliru
But if you remove the noexcept specification, you wouldn't abruptly end your program, exception handling will continue normally. :-).
I'll leave you to think of the consequences if you do this kind of thing in production or even a large code base with many contributors. Do not use noexcept if you are unsure of the exception guarantees of all the statements in your function/constructor block
Yes, a noexcept on a constructor applies to base class/member construction.
If you need to deal with such a case, you probably want to use the little-known (and rarely used) function try block. The syntax looks something like this:
#include <iostream>
class bad_initializer {};
int do_throw() {
throw bad_initializer();
return 1;
}
class something {
int member;
public:
something() noexcept
try : member{do_throw()} // <-- initializer list
{
// ctor body goes here
}
catch(bad_initializer const &) {
std::cerr << "initialization threw\n";
}
};
int main() {
something s;
}
Now, the bad news: since you have a member that wasn't constructed, the catch block really has only a few options. Normal processing can't continue--an exception happened in constructing the object, which means the object can't ever finish construction. By the time you catch the exception, there's nothing you can do about that.
If it weren't noexcept, it could catch the exception, then do some processing (release any resources it did acquire successfully) then either rethrow the exception it caught, or throw a different exception (one that better reflected its inability to be constructed).
In this case, your meaningful choices are even more restricted: you can call terminate directly, or you can throw an exception, which will call terminate indirectly. About all the whole try/catch thing has done in this case is give you a chance to do a little processing before terminate gets called.
In general it's not okay, but in certain circumstances it may be
noexcept is a promise, similar to the const qualifier of member functions, but unlike const it's not enforced at compile time (the compiler will not issue an error and perhaps not even a warning, if a noexcept function may actually throw, but see below). Thus, you can declare a function noexcept even if a compiler-generated check would find that this function may throw and the code will compile (otherwise your question would be impossible).
However, that defeats the purpose of noexcept. The main purpose is to indicate (1) to the programmer that they can use a certain functionality without worrying about exception safety, and (2) to the compiler that it does not need to add code for stack unwinding. Instead, if an exception is thrown in a noexcept function, the run-time will invoke std::terminate(), as required by the standard.
So, in general your constructor should only be noexcept, if all its functionality, including the construction of bases and members is too.
However, there is an exception. If you know that some method will never throw given any input possible in the particular situation, even if it may throw under other circumstances and hence not be noexcept, you can call this method in a noexcept situation. For example,
// requires non-negative x, will throw std::runtime_error for negative x
int my_func(std::int64_t x);
struct my_struct {
std::int64_t q;
my_struct(int x) noexcept : q(std::int64_t(x)*std::int64_t(x)) {}
int member() const noexcept { return my_func(q); } // fine: q>=0
};
In the situation of your post, this means if member(somethingelse_type) is not noexcept, but you know (from conditions outside the code snipped in your post) that no exception will be thrown for the particular argument provided in this circumstance, you may declare Something(SomethingElse) noexcept.
I'm trying to write a unit test that detects an invalid use of the lock() feature of my class. In order to do so, I want to use the destructor and throw an exception from there. Unfortunately, instead of catching the exception, g++ decides to call std::terminate().
There is a very simplified version of the class:
class A
{
public:
A() : f_lock(0) {}
~A() { if(f_lock) throw my_exception("still locked"); }
lock() { ++f_lock; }
unlock() { --f_lock; }
private:
int f_lock;
};
There is a valid test:
A *a = new A;
a->lock();
...
a->unlock();
delete a;
There is the invalid test I'm trying to write:
A *a = new A;
a->lock();
...
bool success = false;
try
{
delete a;
}
catch(my_exception const&)
{
success = true;
}
catch(...)
{
// anything else is a failure
}
if(!success)
{
// test failed...
CPPUNIT_ASSERT(!"test failed");
}
Right now, the delete calls std::terminate() even though the throw is not being called when another exception is active. (i.e. std::uncaught_exception() is false.) And also I clearly am catch all exceptions!
Am I doing something wrong, or is g++ programmed to do that always in destructors?
Update:
The answer by dyp in the comments below works! The following does not directly call std::terminate():
~A() noexcept(false) { throw ...; }
Also for reference about why you do not want a throw in a destructor, this page is excellent;
https://www.securecoding.cert.org/confluence/display/cplusplus/ERR33-CPP.+Destructors+must+not+throw+exceptions
For clarification, there is the full version of the destructor. As we can see I first post a message (it generally goes in your console, may go to a log too). Second I make sure we're not already managing an exception. Finally, I throw an exception named exception_exit which is expected to force a terminate() although in a GUI application you may want to show a MessageBox of some sort to let the user know something happened (since you can capture the Message, you can display that to the user) and then force an application shut down.
Node::~Node() noexcept(false)
{
if(f_lock > 0)
{
// Argh! A throw in a destructor... Yet this is a fatal
// error and it should never ever happen except in our
// unit tests to verify that it does catch such a bug
Message msg(message_level_t::MESSAGE_LEVEL_FATAL, err_code_t::AS_ERR_NOT_ALLOWED);
msg << "a node got deleted while still locked.";
// for security reasons, we do not try to throw another
// exception if the system is already trying to process
// an existing exception
if(std::uncaught_exception())
{
// still we cannot continue...
std::abort();
}
throw exception_exit(1, "a node got deleted while still locked.");
}
}
Also, another detail, you are expected to use the NodeLock object to manage the f_lock flag. That is exception safe since it uses RAII (i.e. a scoped lock). However, at this point I did not want to force the user to make use of the NodeLock to lock/unlock a node, hence this test in the destructor.
In C++11 the noexcept keyword was added. This can be used in function exception specifications:
noexcept(true) is the same as throw(), i.e. this function terminates if anything is thrown
noexcept(false) means the function may throw anything
For most functions, they don't have an exception-specification unless you give them one. A function with no exception-specification may throw anything.
There is a special case for destructors though, found in C++11 [class.dtor]/3:
A declaration of a destructor that does not have an exception-specification is implicitly considered to have the same exception-specification as an implicit declaration (15.4).
The referenced rule, 15.4, says that implicitly-declared special member functions always have an exception-specification. The specification is determined by the following rule, [except.spec]/14:
An implicitly declared special member function (Clause 12) shall have an exception-specification. If f is an implicitly declared default constructor, copy constructor, move constructor, destructor, copy assignment operator, or move assignment operator, its implicit exception-specification specifies the type-id T if and only if T is allowed by the exception-specification of a function directly invoked by f’s implicit definition; f shall allow all exceptions if any function it directly invokes allows all exceptions, and f shall allow no exceptions if every function it directly invokes allows no exceptions.
The "function it directly invokes" in this clause means the destructor of any member variable or base class (applied recursively). If there is no such function , then there are no exceptions allowed by such a function, so the default is noexcept(true).
We could summarise the portion of the above quote relating to your code like this:
If all subobjects either have no destructor, or implicitly-generated destructor, or destructor declared as noexcept(true) or equivalent; then this class's destructor defaults to noexcept(true).
So, changing your destructor to have noexcept(false) would reproduce the behaviour of C++03.
In C++03 none of this appeared and your destructor would have defaulted to allowing all exceptions. I don't know for sure why this change was made in C++11, but it may be because it is a bad idea to throw from a destructor unless you really know what you are doing.
Detailed explanation available at http://www.parashift.com/c++-faq/dtors-shouldnt-throw.html. Better explanation than my own words :)
Excerpt :
You can throw an exception in a destructor, but that exception must not leave the destructor; if a destructor exits by emitting an exception, all kinds of bad things are likely to happen because the basic rules of the standard library and the language itself will be violated. Don’t do it
When implementing the non-throwing swap idiom, should I use throw()?
namespace A
{
struct B
{
void swap( B& other ) throw()
{ /* fancy stuff that doesn't throw */ }
};
void swap( B& lhs, B& rhs ) throw()
{ lhs.swap(rhs); }
}
namespace std
{
template<>
void swap( A::B& lhs, A::B& rhs ) throw()
{ lhs.swap(rhs); }
}
In particular I worry about putting the throw() specification on the specialization of std::swap.
Bonus question:
Is the answer different when using C++0x's noexcept keyword?
In C++03 you can put it there, but if it's true that the fancy stuff doesn't throw, it's basically just documentation. It may or may not affect performance by adding the equivalent of try / catch(...) { std::unexpected(); } around calls to the function: it's up to the implementation whether it can do it without affecting performance.
If you're planning to use the noexcept operator (5.3.7) in C++0x, then suddenly it becomes worth having non-throwing exception specifications, so that the operator gives the "right" answer. I don't really know what the noexcept operator is for, but if there's a clever generic use for it, for example algorithms that become more efficient when something is non-throwing, then I guess it's going to become necessary to mark functions as non-throwing, to get whatever the benefit is.
For example:
void foo() noexcept;
void bar();
template <void(*FUNC)()>
void generic_thing() {
if (noexcept(FUNC()) {
// this won't throw, perhaps we can somehow take advantage of that
FUNC();
} else {
// this might throw
FUNC();
}
}
Old style exception specifications (dynamic-exception-specification) are deprecated in C++0x (and pointless in C++03).
It's not a good idea, no. The reason is that the standard knows that at times it's impossible to enforce the throw() correctness, which is what throw() was brought in for in the first place. In particular, in the case of templates where an exception may or may not be thrown depending on the instantiation it's impossible to check for correctness without the template instantiation. The standard therefore doesn't even require compilers to enforce the exception specifier; in fact, it forbids an implementation from rejecting an expression "merely because when executed it throws or might throw an exception that the containing function does not allow" (15.4/11).
If throw() has no effect other than documentation then it should be commented out; this way at least it doesn't pose a risk of misleading the human observer.
The case with noexcept is wholly different. noexcept comes to be for a different reason; that of performance. If you can guarantee the compiler no exception is thrown then the compiler allows itself to perform some optimizations. But you will have to do the checks yourself. So, if indeed swap() doesn't throw (and it shouldn't; that's its raison d'être) then specifying noexcept is a good idea.
Realistically, no. Exception specifications were a lovely idea, but the reality of them was that they hindered more than helped the majority of code. Nobody uses them and they're deprecated in C++0x. Don't spend time writing exception specifications in modern C++.