I am designing an exception hierarchy in C++ for my library. The "hierarchy" is 4 classes derived from std::runtime_error. I would like to avoid the slicing problem for the exception classes so made the copy constructors protected. But apparently gcc requires to call the copy constructor when throwing instances of them, so complains about the protected copy constructors. Visual C++ 8.0 compiles the same code fine. Are there any portable way to defuse the slicing problem for exception classes? Does the standard say anything about whether an implementation could/should require copy constructor of a class which is to be thrown?
Your exception needs to have a public copy constructor. The compiler has to be able to copy it around for exception handling to work.
The solution to your problem is to always catch by reference instead:
try {
// some code...
throw MyException("lp0 is on fire!");
} catch (MyException const &ex) {
// handle exception
}
(const-ness is optional, but I always put it in because there's rarely a need to modify the exception object.)
Thomas's answer is correct, but I'd also like to suggest you not waste your time by "designing an exception hierarchy". Designing class hierarchies is a notably bad idea, particularly when you could simply derive a couple (and no more than that) of new exception types from the C++ Standard exception classes.
I would steer clear of designing an exception hierarchy distinct to your library. Use the std::exception hierarchy as much as possible and always derive your exceptions from something within that hierarchy. You might want to read the exceptions portion of Marshall Cline's C++ FAQ - read FAQ 17.6, 17.9, 17.10, and 17.12 in particular.
As for "forcing users to catch by reference", I don't know of a good way of doing it. The only way that I have come up with in an hour or so of playing (it is Sunday afternoon) is based on polymorphic throwing:
class foo_exception {
public:
explicit foo_exception(std::string msg_): m_msg(msg_) {}
virtual ~foo_exception() {}
virtual void raise() { throw *this; }
virtual std::string const& msg() const { return m_msg; }
protected:
foo_exception(foo_exception const& other): m_msg(other.m_msg) {}
private:
std::string m_msg;
};
class bar_exception: public foo_exception {
public:
explicit bar_exception(std::string msg_):
foo_exception(msg_), m_error_number(errno) {}
virtual void raise() { throw *this; }
int error_number() const { return m_error_number; }
protected:
bar_exception(bar_exception const& other):
foo_exception(other), m_error_number(other.m_error_number) {}
private:
int m_error_number;
};
The idea is to make the copy constructor protected and force users to call Class(args).raise() instead of throw Class(args). This lets you throw a polymorphicly bound exception that your users can only catch by reference. Any attempt to catch by value should be greeted with a nice compiler warning. Something like:
foo.cpp:59: error: ‘bar_exception::bar_exception(const bar_exception&)’ is protected
foo.cpp:103: error: within this context
Of course this all comes at a price since you can no longer use throw explicitly or you will be greeted with a similar compiler warning:
foo.cpp: In function ‘void h()’:
foo.cpp:31: error: ‘foo_exception::foo_exception(const foo_exception&)’ is protected
foo.cpp:93: error: within this context
foo.cpp:31: error: ‘foo_exception::foo_exception(const foo_exception&)’ is protected
foo.cpp:93: error: within this context
Overall, I would rely on coding standards and documentation stating the you should always catch by reference. Make sure that your library catches exceptions that it handles by reference and throw fresh objects (e.g., throw Class(constructorArgs) or throw;). I would expect other C++ programmers to have the same knowledge - but add a note to any documentation just to be sure.
The two portable ways I have found to stop clients of my library from catching exceptions incorrectly by value are
Throw exceptions from inside virtual raise methods of the exception classes, and make copy constructors protected. (Thanks D.Shawley)
Throw derived exceptions from the library and publish exception base classes for clients to catch. The base classes could have protected copy constructors, which only allows the good way of catching them. (mentioned here for a simmilar question)
The C++ standard does state that copy constructor needs to be accessible at the point of throw. Visual C++ 8.0 in my configuration violated this part of the standard by not enforcing the presence of the copy constructor. In section 15.1.3:
A throw-expression initializes a temporary object, the type of which is determined by removing any top-level cv-qualifiers from the static type of the operand of throw and adjusting the type from “array of T” or “function returning T” to “pointer to T” or “pointer to function returning T”, respectively.
If the use of the temporary object can be eliminated without changing the meaning of the program except for the execution of constructors and destructors associated with the use of the temporary object (12.2), then the exception in the handler can be initialized directly with the argument of the throw expression. When the thrown object is a class object, and the copy constructor used to initialize the temporary copy is not accessible, the program is ill-formed (even when the temporary object could otherwise be eliminated)
This answer was posted by OP into the question, I removed it from the question and posted as a separate answer.
I'd say to not use any of the built in C++ exception code. If you must have exceptions, create your own from scratch. That's the only way to be sure they will behave similar let alone be implemented in a similar manner, and to be blunt the implementation of exceptions in C++ is incompetent.
Related
When writing exception-safe code, should all private member functions guarantee at least basic exception safety? What would be best/good practice in this situation? Alternatives?
For example, say I have a class Foo with public function member DoSomething, which calls private function member DoSomeOfIt. DoSomeOfIt may fail due to some functions that I cannot influence, and when it does it may leave the Foo object in a partially modified state which violates Foo's invariants. So I could wrap DoSomeOfIt in a try-catch block and call another private function member UndoThat in the catch block to undo what DoSomeOfIt did. Individually, DoSomeOfIt and UndoThat may not be exception safe, but DoSomething is. Would that be exception safe code? (In this case with strong guarantee)
class Foo {
public:
// I provide strong exception safety guarantee
void DoSomething() {
try {
DoSomeOfIt();
} catch (const std::exception& e) {
UndoThat();
throw;
}
}
private:
// I provide no exception safety guarantee.
DoSomeOfIt() {
// may throw and violate class invariants.
}
// I provide no exception safety guarantee.
UndoThat() {
// undoes everything most recent call of
// DoSomeOfIt did.
}
};
Of course I could simply include the code of DoSomeOfIt and UndoThat in DoSomething, but that could lead to code bloating, and a long function body, whereas breaking up the functions modularizes the tasks and may make the code more readable(?)
DISCLAIMER:
I understand this may be opinion-based. I am not sure if that makes this a bad post, but I'd appreciate any opinions, or experiences where this has lead to issues, or is common practice etc.
This is my opinion.
If there is a possibility that DoSomeOfIt will be used by more than one function, it'll be better to have the exception handling code reside in that function itself -- you don't want to have the exception handling code duplicated across multiple functions. If that is not a possibility, your posted code is fine.
Having said that, if you move the exception handling code to DoSomething, you don't lose anything. In fact, the function becomes better. If it is used in the future by another function, the exception handling is already taken care of. Looked at from that point of view, it will be better to move the exception handling code to DoSomething.
I'm currently trying to implement a really small nested exception mechanism in my code, as std::nested_exceptions aren't available for all the compilers I must compile my code with.
I came across the following useful nesting wrapper in the gcc implementation source code:
template<typename _Except>
struct _Nested_exception : public _Except, public nested_exception
{
explicit _Nested_exception(_Except&& __ex)
: _Except(static_cast<_Except&&>(__ex))
{ }
};
which allows to combine an exception that has been thrown with the nested_exception class in throw_with_nested so that one can dynamic_cast to test whether the exception we've caught is actually a nested exception or not later on.
What I don't understand is the static_cast here. I think I'm missing something about move-semantics, is it really needed?
Although __ex is an _Except&&, once you enter this scope __ex is an lvalue - it's a local variable. To enforce the use of the move constructor inside of _Except they do _Except(static_cast<_Except&&>(__ex)) to force __ex to become an rvalue (it's probably actually an xvalue).
Move semantics means that we know that this constructor has been called with a parameter that is a temporary (or to-be-moved-from object). We see this in the type of __ex which is _Except&&. However if we were to use __ex within this constructor it would be treated as an lvalue - it clearly has a name and we can take it's address.
If you want to pass __ex to any further functions/constructors, it's rvalue-ness needs to be restored. The normal way to do so is by calling std::move(__ex) which will reapply && to the type of __ex. This is really just the same static_cast that you see above.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am coming from a Ruby and Java background and have recently begun exploring C++.
While my initial attempts at creating custom exceptions by simply subclassing exception class failed with obscure, I found the following example posted on a site:
class Exception : public exception
{
public:
Exception(string m="exception!") : msg(m) {}
~Exception() throw() {}
const char* what() const throw() { return msg.c_str(); }
private:
string msg;
};
My understanding of semantics of C++ is not very mature at the moment, and I would like to have a better understanding of what is going on here.
In the statement const char* what() const throw() what does the part const throw() do, and what kind of programming construct is it?
Also, what is the purpose and intent of throw() in the destructor specification ~Exception() and why do I need to have a destructor specification although I don't need it do something in particular? Shouldn't the destructor inherited from exception be sufficient?
const after a method declares that the method does not mutate the object. (There are exceptions, and generally it's used to mean "does not mutate the object in an externally-visible way.)
The throw() after the method declaration is an exception specification; it's similar to the throws E1, E2 exception specifications that you see in Java. However, in C++, exception specifications are not checked at compilation-time and are generally considered to be mostly useless (they are now deprecated). throw() is the only somewhat useful form, meaning that the function declares that it must not throw an exception (and if it does, it's a logical error, and the program will invoke an unexpected exception handler, by default terminating the program).
The destructor is explicitly declared because if left unspecified, the compiler will generate a destructor that invokes the base class destructor, and the compiler-generated destructor will not use a throw() exception specification (despite the fact that throwing exceptions in destructors is never a good idea).
You are currently dealing with some style things of C++!
So when you want to actually have an exception-object you may use std::exception, which is explained here on cppreference.
But since you could throw and catch everything in C++, you may even define your own exception class or use more basic aspects, e.g.
try {
throw("S0M3, M4YB3 CR1PT1C STR1NG!");
} catch(char const* exceptStr) {
SomeFuncThatDecodesTheString(exceptStr);
}
Your other topics are more a kind of personal style or standard:
An empty destructor like ~FooClass() {} is only there two show "I really do nothing!". Sometimes they might also be useful, when you use a strict system for writing your classes (e.g. First the public space, including the standard ctor at first and the standard dtor as the second function ...) to kind of force you (or some other coder) to write into the existing braces/function and therefore not desroying your holy order :)
You may write a throw() behind classes for insurance to other people, that the class does only throw exceptions of the types stated in the parantheses. Therefore a function void FooFunc() throw(int,char) should only throw ints and chars. And an empty throw() is just to actually say "Hey coder, I do not throw anything!". You will often find this in the C++ standard library, since you are (mostly) only able to look at the prototypes and not the source. BTW the throw(someType(s)) might be a lie. The function may throw any other type or simply nothing! But don't be a liar, when you use this ;)
EDIT:
I wanted to add, that noexcept can (since C++11) also be used to declare an function, not to throw any exception. This is pretty more comprehensible than throw().
LG ntor
throw() in the destructor specification means that the destructor doesn't throw exceptions. Destructors in C++ should not throw exceptions - here is why.
Destructors in C++ are not inherited. If you don't write your own destructor then compiler will automatically generate a destructor for you. That destructor will call destructor of a base class if such class exists.
const specifier in Exception::what() declaration means that this method may be called for constant objects of type Exception. throw() specifier means the same as for the destructor.
You should get a book about C++, those are very basic questions.
std::exception requires that its constructor be throw(). Yet std::runtime_error accepts a std::string as its argument, which indicates that it's storing a std::string somewhere. Therefore, an assignment or copy construction has to be going on somewhere. And for std::string, that's not a nothrow operation.
How then does runtime_error::runtime_error meet throw()?
(For context, I'm implementing an exception type, and want to store a few std::strings from the call site, and I want to do it correctly...)
(Here's the same thing in a minimal-ish testcase.)
runtime_error::runtime_error(string const&) doesn't need to meet throw().
It doesn't inherit from or override exception::exception(), and by the time string's copy constructor is invoked, exception::exception() has completed.
If copying the string were to throw an exception, this would unwind runtime_error::runtime_error(string const&) and then, I suppose, invoke exception::~exception().
It's hard to directly show that there is no requirement of a derived ctor to meet a base ctor's exception specifier, but it is strongly implied by the following passage (which describes how the base's destructor is invoked, rather than passing the exception into the base constructor):
[2003: 15.2/2] An object that is partially constructed or
partially destroyed will have destructors executed for all of its
fully constructed subobjects, that is, for subobjects for which the
constructor has completed execution and the destructor has not yet
begun execution. Should a constructor for an element of an automatic
array throw an exception, only the constructed elements of that array
will be destroyed. If the object or array was allocated in a
new-expression, the matching deallocation function (3.7.3.2, 5.3.4,
12.5), if any, is called to free the storage occupied by the object.
The only passage which comes even close to the scenario you presumed (and which I initially presumed) is the following.
[2003: 15.4/3] If a virtual function has an exception-specification,
all declarations, including the definition, of any function that
overrides that virtual function in any derived class shall only allow
exceptions that are allowed by the exception-specification of the base
class virtual function.
But clearly exception::exception() is not a virtual function, and clearly runtime_error::runtime_error(string const&) does not override it.
(Note that this scenario would apply for a virtual destructor; accordingly, you can see that, in libstdc++, runtime_error::~runtime_error() is throw()).
Update, 2015:
Yet std::runtime_error accepts a std::string as its argument, which indicates that it's storing a std::string somewhere. Therefore, an assignment or copy construction has to be going on somewhere. And for std::string, that's not a noexcept operation.
runtime_error (and logic_error) are only required to accept an argument of type std::string const &. They are not required to copy it.
Use these overloads at your own peril. LLVM libc++ does not provide storage.
On the other hand, GNU libstdc++ tiptoes carefully to avoid running out of memory. It copies the contents of the string, but into the exception storage space, not into a new std::string.
Even then, it adds an std::string&& overload and uses friendship to adopt the internal buffer of a std::string argument passed by rvalue, to conserve exception storage space too.
So that's your real answer: "Very carefully, if at all."
You could leverage GCC's generosity by using std::runtime_errors as members of your own exception class, storing one string each. This would still be useless on Clang, though.
Original answer, 2011. This is still true:
An exception during stack unwinding causes terminate to be called.
But constructing the object to be thrown is not part of unwinding, and is treated no differently from the code before the throw expression.
If std::runtime_error::runtime_error( std::string const & ) throws std::bad_alloc, the runtime_error exception is lost (it never existed) and the bad_alloc is handled instead.
Demonstration: http://ideone.com/QYPj3
As for your own class storing std::strings from the call site, you'll want to follow §18.8.1/2:
Each standard library class T that derives from class exception shall have a publicly accessible copy constructor and a publicly accessible copy assignment operator that do not exit with an exception.
This is required because copying from the stack to the thread's exception storage is sensitive to exceptions. §15.1/7:
If the exception handling mechanism, after completing evaluation of the expression to be thrown but before the exception is caught, calls a function that exits via an exception, std::terminate is called (15.5.1).
So, you should use a shared_ptr< std::string > or some such to sanitize copies after the first.
Once in a while, I notice some coding pattern that I've had for years and it makes me nervous. I don't have a specific problem, but I also don't remember enough about why I adopted that pattern, and some aspect of it seems to match some anti-pattern. This has recently happened to me WRT how some of my code uses exceptions.
The worrying thing involves cases where I catch an exception "by reference", treating it in a similar way to how I'd treat a parameter to a function. One reason to do this is so I can have an inheritance hierarchy of exception classes, and specify a more general or more precise catch type depending on the application. For example, I might define...
class widget_error {};
class widget_error_all_wibbly : public widget_error {};
class widget_error_all_wobbly : public widget_error {};
void wibbly_widget ()
{
throw widget_error_all_wibbly ();
}
void wobbly_widget ()
{
throw widget_error_all_wobbly ();
}
void call_unknown_widget (void (*p_widget) ())
{
try
{
p_widget ();
}
catch (const widget_error &p_exception)
{
// Catches either widget_error_all_wibbly or
// widget_error_all_wobbly, or a plain widget_error if that
// is ever thrown by anything.
}
}
This is now worrying me because I've noticed that a class instance is constructed (as part of the throw) within a function, but is referenced (via the p_Exception catch-clause "parameter") after that function has exited. This is normally an anti-pattern - a reference or pointer to a local variable or temporary created within a function, but passed out when the function exits, is normally a dangling reference/pointer since the local variable/temporary is destructed and the memory freed when the function exits.
Some quick tests suggest that the throw above is probably OK - the instance constructed in the throw clause isn't destructed when the function exits, but is destructed when the catch-clause that handles it completes - unless the catch block rethrows the exception, in which case the next catch block does this job.
My remaining nervousness is because a test run in one or two compilers is no proof of what the standard says, and since my experience says that what I think is common sense is often different to what the language guarantees.
So - is this pattern of handling exceptions (catching them using a reference type) safe? Or should I be doing something else, such as...
Catching (and explicitly deleting) pointers to heap-allocated instances instead of references to something that looks (when thrown) very like a temporary?
Using a smart pointer class?
Using "pass-by-value" catch clauses, and accepting that I cannot catch any exception class from a hierarchy with one catch clause?
Something I haven't thought of?
This is ok. It's actually good to catch exceptions by constant reference (and bad to catch pointers). Catching by value creates an unnecessary copy. The compiler is smart enough to handle the exception (and its destruction) properly -- just don't try to use the exception reference outside of your catch block ;-)
In fact, what I often do is to inherit my hierarchy from std::runtime_error (which inherits from std::exception). Then I can use .what(), and use even fewer catch blocks while handling more exceptions.
This pattern is definitely safe.
There are special rules that extend the lifetime of a thrown object. Effectively, it exists as long as it is being handled and it is guaranteed to exist until the end of the last catch block that handles it.
One very common idiom, for example, to derive custom exceptions from std::exception, override its what() member function, and catch it by reference so that you can print error messages from a wide variety of exceptions with one catch clause.
No, you're definitely doing it right. See http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.13 , and the rest of the FAQ chapter for that matter.
Yes. So far so good.
Personally I use std::runtime_error as the base of all exception calsses. It handles error messages etc.
Also don't declare more exceptions that you need to. Define an exception only for things that can actually be caught and fixed. Use a more generic exception for things that can not be caught or fixed.
For example: If I develop a library A. Then I will have an AException derived from std::runtime_error. This exception will be used for all generic exceptions from the library. For any specific exceptions where the user of the library can actually catch and do something (fix or mitigate) with the exception then I will create a specific exception derived from AException (but only if there is something that can be done with the exception).
Indeed, Sutter and Alexandrescu recomend this pattern in their 'C++ Coding Standards'.