I'm trying to write an exception class that needs to be thrown when a system call fails. The exception should have a developer message and the errno code, and it's what method should format the developer message along with the error code. The C way to do the formatting is snprintf, but I'm trying to avoid that. I tried defining a class member for the exception of type std::stringstream. However, that did not work since stringstream has a private copy constructor. Looking for an alternative I learned about Boost's format object. I tried using it and got a different error:
In file included from tun_device.cc:7:0:
system_error.h:9:7: error: looser throw specifier for ‘virtual SystemError::~SystemError()’
class SystemError : public exception
^
In file included from system_error.h:4:0,
from tun_device.cc:7:
/usr/include/c++/4.8/exception:64:13: error: overriding ‘virtual std::exception::~exception() throw ()’
virtual ~exception() _GLIBCXX_USE_NOEXCEPT;
The way to solve this was to define my own destructor:
~SystemError() throw() {
}
As I understand, this line specifies that the destructor of this exception should not throw any exceptions.
Here's the complete class:
class SystemError : public exception
{
public:
int m_errno;
const char * m_message;
SystemError(int err, const char * message) :
fmt("%1%: %2%") {
fmt % message % errno;
m_errno = err;
this->m_message = message;
}
const char * what() const throw(){
return fmt.str().c_str();
}
~SystemError() throw() {
}
private:
format fmt;
};
I have several questions:
First of all - Am I reinventing the wheel? Is already there a recommended C++ way to handle failed system calls?
Why does using the format class as a member of the exception forces me to override the default destructor?
Is there any pitfall I should be aware of now that I added my own destructor?
Is there a way to achieve what I want using only the standard C++ library?
Exception can be handled using the standard exception class or creating your own classes derived from std::exception class. Inheritance would be used when you would want to extend the already available functionality available using std::exception. So the decision is totally dependent on how you want design your application.
boost::format does not force you to override the destructor. If you notice you are deriving from std::exception and composing boost::format. std::exception destructor is declared as virtual and has a no throw nature.
virtual ~exception() throw();
When you leave out the destructor, compiler implicitly provides a destructor, but this destructor does not have no throw() nature, hence compile error:
format.cpp:5: error: looser throw specifier for âvirtual SystemError::~SystemError()â
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/exception:63: error: overriding âvirtual std::exception::~exception() throw ()â
When you provide a constructor but as:
~SystemError(); //since the base class std::exception has a destrutor with no throw, the child should also follow the same, and again in this case compile time error is received:
format.cpp:25: error: looser throw specifier for âvirtual SystemError::~SystemError()â
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/exception:63: error: overriding âvirtual std::exception::~exception() throw ()â
To resolve the error SystemError should define a destructor like this:
~SystemeError() throw();
Sample SSCCE code:
#include <iostream>
#include<boost/format.hpp>
class SystemError : public std::exception
{
public:
int m_errno;
const char * m_message;
SystemError(int err, const char * message) :
fmt("%1%: %2%") {
fmt % message % err;
m_errno = err;
this->m_message = message;
}
const char * what() const throw(){
return fmt.str().c_str();
}
~SystemError() throw() {
}
// ~SystemError() {
//
// }
private:
boost::format fmt;
};
int main(){
return 0;
}
Adding destructor is like taking responsibilities of your actions. Destructor could be used to clear any heap memory assigned in the class. Absence of destructor would lead compiler to provide an implicit destructor, which could be cause of issues in specific cases.
The compilation error will not be received if the class in discussion has primitive data types.
Related
What does this error mean? How can I fix it? This is the header code that's causing it:
class BadJumbleException : public exception {
public:
BadJumbleException (const string& msg); // Constructor, accepts a string as the message
string& what(); // Returns the message string
private:
string message; // Stores the exception message
};
And this is the source code:
BadJumbleException::BadJumbleException (const string& m) : message(m) {}
string& BadJumbleException::what() { return message; }
EDIT: This is the error:
looser throw specifier for 'virtual BadJumbleException::~BadJumbleException()
In C++03, per §18.6.1/5, std::exception has a destructor that is declared such that no exceptions can be thrown out of it (a compilation error will be caused instead).
The language requires that when you derive from such a type, your own destructor must have the same restriction:
virtual BadJumbleException::~BadJumbleException() throw() {}
// ^^^^^^^
This is because an overriding function may not have a looser throw specification.
In C++11, std::exception::~exception is not marked throw() (or noexcept) explicitly in the library code, but all destructors are noexcept(true) by default.
Since that rule would include your destructor and allow your program to compile, this leads me to conclude that you are not really compiling as C++11.
I was playing with c++ exceptions and I've tried throwing an anonymous exception like this:
throw class : public std::exception
{
virtual const char *what() const noexcept
{
return "Custom exception";
}
} ex;
However I'm getting the following error when trying to compile:
error: expected primary-expression before ‘class’
throw class : public std::exception
^
My compiler is gcc 5.2.1 on Linux x86_64.
How can I achieve the desired result?
This is not an answer per-se, but some important information what will help you going forward:
First, throwing an anonymous exception is unlikely to be useful. Exceptions are caught by their type. If you can't name the type, you can't catch the exception explicitly - only by its base, in which case you may as well have just thrown the base.
Second (and this is important):
There's rarely a good reason to derive from std::exception directly. You should derive from one of the exception types defined in <stdexcept>
these are:
std::runtime_error - indicating that some runtime condition makes it impossible to perform the service at the moment (such as a missing file).
std::logic_error - indicating that what was attempted will never be possible and the program is fundamentally in error in a way that could not be detected at compile time.
Handy reference here:
http://en.cppreference.com/w/cpp/header/stdexcept
You can't declare a class in a throw statement. Declare the class first (anonymously if you like, naming it via a typedef), then you can throw it.
Better is to name the exception class, but put it in the nameless namespace:
namespace {
class LocalException : public std::exception {
const char *what() const noexcept override {
return "Custom exception";
}
};
}
....
throw LocalException();
or, if you insist, you can create an object of anonymous class, and throw that.
static class : public std::exception {
const char *what() const noexcept override {
return "Custom exception";
}
} LocalExceptionObject;
....
throw LocalExceptionObject;
Edit If you create a typedef, somebody can copy it, and it names the same class. You have to create an object of the anonymous class, and then nobody can name it.
Having said that, I don't think having anonymous things is useful. Far better to declare the class in a nameless namespace (so you know it is private), and just use it.
What does this error mean? How can I fix it? This is the header code that's causing it:
class BadJumbleException : public exception {
public:
BadJumbleException (const string& msg); // Constructor, accepts a string as the message
string& what(); // Returns the message string
private:
string message; // Stores the exception message
};
And this is the source code:
BadJumbleException::BadJumbleException (const string& m) : message(m) {}
string& BadJumbleException::what() { return message; }
EDIT: This is the error:
looser throw specifier for 'virtual BadJumbleException::~BadJumbleException()
In C++03, per §18.6.1/5, std::exception has a destructor that is declared such that no exceptions can be thrown out of it (a compilation error will be caused instead).
The language requires that when you derive from such a type, your own destructor must have the same restriction:
virtual BadJumbleException::~BadJumbleException() throw() {}
// ^^^^^^^
This is because an overriding function may not have a looser throw specification.
In C++11, std::exception::~exception is not marked throw() (or noexcept) explicitly in the library code, but all destructors are noexcept(true) by default.
Since that rule would include your destructor and allow your program to compile, this leads me to conclude that you are not really compiling as C++11.
I have looked at this problem and don't see where the problem is. I'm not an expert at C++ so to me this looks OK. This used to compile without issue the last time I tried.
namespace yaaf {
/************************************************************************/
/* */
/* Standard YAAF Errors */
/* */
/************************************************************************/
/* XGYAAFError
*
* YAAF Error; this is the root of my YAAF errors, and is
* a descendant of the standard exception class
*/
class XGYAAFError : public std::exception {
public:
explicit XGYAAFError(const char *);
explicit XGYAAFError(const std::string &err);
const char *what() const throw()
{
return fError.c_str();
}
private:
std::string fError;
};
} // namespace yaaf
#endif
The GCC library base class...
/**
* #brief Base class for all library exceptions.
*
* This is the base class for all exceptions thrown by the standard
* library, and by certain language expressions. You are free to derive
* your own %exception classes, or use a different hierarchy, or to
* throw non-class data (e.g., fundamental types).
*/
class exception
{
public:
exception() throw() { }
virtual ~exception() throw();
/** Returns a C-style character string describing the general cause
* of the current error. */
virtual const char* what() const throw();
};
The error " specification of overriding function is more lax than base version" is what I now get when I try to build.
I think that this may have to do with a change in the C++ language ( about 2004??) and where you can declare pointer within a derived class. But I'm not sure if that's the case here and how to go about fixing this.
Any ideas on what specifically is wrong or how I can fix this is appreciated.
Thanks
XGYAAFError has a member variable of type std::string, which has a nontrivial destructor that can throw any exception. std::exception, as you see, has a user-declared destructor that is declared as throwing no exceptions.
Therefore, because of the overriding rules, XGYAAFError needs a user-declared destructor with a throw() exception specification. I provided an in-depth explanation of this subject in the question, "How does an exception specification affect virtual destructor overriding?" See that question for details.
I have run into broken compiler, which does not allow exceptions to inherit from std::exception (nvcc 3.0).
so had to create workaround:
struct exception {
explicit exception(const char* message) {
what_ = message;
}
virtual const char *what() const throw() { return what_; }
operator std::exception() const {
return std::runtime_error(what_);
}
private:
const char* what_;
};
struct configuration_error : exception {
configuration_error(const char* message)
: exception(message) {}
};
is there something I am going to lose by not inheriting from exception, instead providing cast? is what necessary in the above case?
thank you
catch (std::exception) will not catch your exception, and you cannot dynamic_cast your exception to std::exception either. If your program never does either of those things, you're fine.
Personally I would not use a compiler this broken, though.
You should upgrade to CUDA 3.1.
If you're trying to create an instance of something derived from std::exception on the device, it won't work because the std::exception constructor would need to be called, and that is not a device function.
Throwing and catching your own type is probably the solution. Since it probably will never make it back to host code, though (C++ doesn't really handle throwing multiple exceptions in parallel), compatibility with std::exception shouldn't be too much of an issue.