I came from c++98, and i am trying to make my way in to c++11 and so on. i came across the public member function , std::exception::what, <=> virtual const char* what() const noexcept;
from this example givin in c++ reference : what_example, i can understand the usage but i have a few questions:
// exception::what
#include <iostream> // std::cout
#include <exception> // std::exception
struct ooops : std::exception {
const char* what() const noexcept {return "Ooops!\n";}
};
int main () {
try {
throw ooops();
} catch (std::exception& ex) {
std::cout << ex.what();
}
return 0;
}
in c++98 the what() was : virtual const char* what() const throw();, and in c++11, it becomes virtual const char* what() const noexcept;. what is the noexcept at the end? did it bring something new?
why should i use what() it at all? i can emplement my own tostring method in my class exception and call it instead!
in the return value of what(), see below, guaranteed to be valid at least until...or until a non-const member function of the exception object is called. what is the meaning of or until a non-const member function of the exception object is called, could some one explain with example and why is that ?
what() return value
A pointer to a c-string with content related to the exception. This is
guaranteed to be valid at least until the exception object from which
it is obtained is destroyed or until a non-const member function of
the exception object is called.
thanks.
what is the noexcept at the end?
It is a new specifier introduced in C++11. In very short, it means that the function will not throw an exception. noexcept has same meaning as throw().
did it bring something new?
noexcept is an improvement over the old throw specifier, which has since been deprecated (C++11) and then removed (C++20) from the language. It accepts a boolean expression that determines whether the function is noexcept or potentially throwing. This is useful in generic template programming because some instances of a template may be potentially throwing while others might not be.
why should i use what() it at all? i can emplement my own tostring method in my class exception and call it instead!
Because you may be using functions that are not written by you, and therefore will not throw your exception class. For example, some standard functions will in some cases throw an exception, and all standard exceptions derive from std::exception. In such case, the only way to access the error message is through the what member function.
Same applies when other people call your function. They might not want to / or need to know about your special exception class, but they can still catch it and print the message if you inherit std::exception.
what is the meaning of or until a non-const member function of the exception object is called
The meaning is literal. If you call what on an exception object derived from std::exception, and store the returned pointer, and then call a non-const member function of that exception object then the stored pointer will be invalid.
Any attempt to indirect through an invalid pointer such as attempting to print the exception message will result in undefined behaviour.
For your first question check out StoryTeller's comment. As for the second point:
why should i use what() it at all? i can emplement my
own tostring method in my class exception and call it instead!
The first rule of programming is do not reinvent the wheel, if there is a toString function or another function in the STL library that meets your needs, use it. Do not invent your own and try to debug it.
As an addition to the third question:
Sometimes, one happens to be surprised how important it can be that the wheel is not reinvented; and sharing the same basic class can be a big deal.
Thus, there comes a std::cerr message showing the contents of what, when the program crashes because of a thrown exception.
Related
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.
I'm writing a exception class with a what() method.
const char* what() const throw() {
return "test";
}
works fine, but
const char* what() const throw() {
return (std::string("test")).c_str();
}
seems to return a random result. Why?
std::string("test") creates a temporary string object. c_str returns a pointer to some internal storage of that temporary object. After the function exits, that’s a dangling pointer – it points to invalid memory.
There is no way to circumvent this. You either have to make your string object more long-lived by declaring (and initialising, since the function is const) it outside the function – or you need to manually allocate heap storage inside the function, copy the string there, and return a pointer to that storage. However, this is complicated, error-prone, and violates the contract of the function, because the user of your error class doesn’t expect to free memory.
In fact, here’s a simple implementation of an error class (toy, since I don’t know your use-case) with this in mind:
struct my_logic_error : std::logic_error {
// `std::logic_error` already overrides `what`, we only need to initialise it!
my_logic_error(int errcode) :
std::logic_error{std::string{"Logic error occurred with error code "} +
std::to_string(errcode)} {}
};
Assuming you derive from an exception class without this luxury, your code gets minimally more complex:
struct my_error : std::exception {
my_error(int errcode) :
message{std::string{"Logic error occurred with error code "} +
std::to_string(errcode)} {}
char const* what() const noexcept {
return message.c_str();
}
private:
std::string message;
};
You store the string value in a member of your exception class, and you return c_str() on this member.
Doing a strdup can work, but the caller must free the memory, that's not a safe way of doing.
The following is a custom exception class from another person's c++ tutorial:
class MyException : public std::exception {
public:
MyException(const std::string message) : m_message(message) { }
~MyException() throw() { }
const std::string what() const throw() { return m_message.c_str(); }
private:
std::string m_message;
}
I get most of what going on here,, except for the "throw()" right next to the destructor..
Does it mean throw() is called whenever the exception class is destructed..??
This is an exception specification.
It means that the destructor is not supposed to throw any exception. If it attempts to throw one anyway, the program will invoke std::terminate (which will almost certainly crash the program). Note that not all compilers implement this behavior correctly (most notably, in VC++ throwing from a destructor declared throw() leads to unspecified behavior).
Note that exception specifications have been deprecated with C++11 in favor of noexcept and should no longer be used (for good reasons). Destructors are implicitly noexcept in C++11.
It's a declaration of what the function is allowed to throw. In this case, nothing.
See http://en.cppreference.com/w/cpp/language/except_spec
If you don't list an exception type inside the throw() and you later try to throw one from that function, you'll get an std::unexpected thrown instead.
If the throw() is left out as it usually is, then any exception may be thrown.
Let's say I Have this:
namespace MyNamespace{
class Exception : public std::runtime_error
{
public:
explicit Exception(const std::string &msg) : std::runtime_error(msg) {}
};
} //namespace MyNamespace
And there is a code somewhere in my program:
try{
foo();
}
catch (const MyNamespace::Exception &exc){
std::cout << exc.what();
}
The question is (I want you to examine me) - will I catch the exception if I write in foo:
1) throw MyNamespace::Exception("Hello world!");
Here i think, yes, I will, because I definitely pointed out the type of exception(and it's necessary couse of "explicit" keyword) and std::string doesn't have "explicit" keyword which means I can throw "Hello world!" instead of std::string("Hello world!")
2) throw MyNamespace::Exception(std::string("Hello world!"));
obviosly, I will.
3) throw "Hello world!";
here i think, no, I won't, cause of keyword "explicit" presence.
4) throw std::string("Hello world");
no (same reason)
and 5) Whould I catch expections from the 3-4 cases if I didn't have explicit keyword? (I think yes)
update:
6) When the temporary object std::string will be created? At what point of time?
Your answers for 1-4 are correct, but the reasoning behind them is a little off.
3) This has nothing to do with explicit keyword. The type of the expression after throw is const char[12] and by the rules the type of the exception thrown is const char*.
4) Again, nothing to do with explicit string constructors, really. The type thrown is std::string and only std::string (with reference or not) type of handler can catch it.
5) So obviously, no.
6) When the exception is thrown.
From the wording in 3-5, you're obviously thinking that C++ attempts to match the throw to the catch statements as if it were picking the best match from overloaded functions to call. That's not the case. The throw statement is considered separately from any catch statements - indeed, you can compile the function foo and its throw statements before the catching code is written, so it can't choose to convert a std::string to some type the catching code ends up looking for... it might not know about that.
The type of value thrown depends entirely on the type of the parameter to throw, as it would be understood in the surrounding context if the expression appeared without throw. For example:
void foo()
{
...
throw XXX;
}
...throws the same type as...
void foo()
{
...
auto what_will_be_thrown = XXX;
throw what_will_be_thrown;
}
Conversions like const char* to std::string are not applied when catching, although you can catch a derived type via a public base class (for references or pointers), and of course you can catch types using const references etc..
Re 6) - whatever the type of the value, it's created just before the Exception constructor is called, just as any for any other function call timing wise, but in this case the object being thrown may be constructed in a separate memory area from the normal call stack, such that it will survive the stack unwinding that happens while looking for a matching catch statement. Exactly how this is orchestrated by the compiler is not specified in the Standard though.
Your rationale for 3 and 4 is wrong, and consequently, so is your answer to 5. Here’s why:
When you catch an exception, no conversion is every performed, except a conversion to base class. So catch (Foo const&) will never catch anything convertible to Foo, except subclasses of Foo. It’s for that reason, and not related to explicit constructors, that your code won’t catch a thrown std::string or char[].
I've just fixed a very subtle bug in our code, caused by slicing of an exception, and I now want to make sure I understand exactly what was happening.
Here's our base exception class, a derived class, and relevant functions:
class Exception
{
public:
// construction
Exception(int code, const char* format="", ...);
virtual ~Exception(void);
<snip - get/set routines and print function>
protected:
private:
int mCode; // thrower sets this
char mMessage[Exception::MessageLen]; // thrower says this FIXME: use String
};
class Derived : public Exception {
public:
Derived (const char* throwerSays) : Exception(1, throwerSays) {};
};
void innercall {
<do stuff>
throw Derived("Bad things happened!");
}
void outercall {
try {
innercall();
}
catch(Exception& e)
{
printf("Exception seen here! %s %d\n", __FILE__, __LINE__);
throw e;
}
}
The bug was of course that outercall ends up throwing an Exception, instead of a Derived. My bug resulted from higher in the call stack attempts to catch the Derived failing.
Now, I just want to make sure I understand - I believe that at the 'throw e' line, a new Exception object is being created, using a default copy constructor. Is that what's really going on?
If so, am I allowed to lock out copy constructors for objects that will be thrown? I'd really prefer this not happen again, and our code has no reason to copy Exception objects (that I know of).
Please, no comments on the fact that we have our own exception hierarchy. That's a bit of old design that I'm working to correct (I'm making good progress. I've gotten rid of the home-grown string class, and many of the home-grown containers.)
UPDATE: To be clear, I had fixed the bug (by changing 'throw e' to 'throw') before I ever asked the question. I was just looking for confirmation of what was going on.
When you throw an object, you're actually throwing a copy of the object, not the original. Think about it - the original object is on the stack, but the stack is being unwound and invalidated.
I believe this is part of the standard, but I don't have a copy to reference.
The type of exception being thrown in the catch block is the base type of the catch, not the type of the object that was thrown. The way around this problem is to throw; rather than throw e; which will throw the original caught exception.
A quick google suggests that yes, you're throwing the copy constructor is required and must be public. (Which makes sense, as you're initializing a copy of e and throwing that.)
Anyway, just use throw without specifying the exception object, to rethrow what was caught in the catch. Shouldn't that solve the problem?
catch(Exception& e)
{
printf("Exception seen here! %s %d\n", __FILE__, __LINE__);
throw;
}
Yes.
throw e;
throws an exception of the static type of e, regardless of whatever e actually is. In this case, the Derived exception is copied to an Exception using a copy constructor.
In this case you can just
throw;
to get the Derived exception bubble up correctly.
If you're interesting in polymorphical throwing in some other cases, refer to the always so useful C++ FAQ Lite.
C++ never ceases to amaze me. I would have lost a lot of money had this been a bet on what was the behaviour!
The exception object is first copied to a temporary and you should have used throw. To quote the standard 15.1/3:
A throw-expression initializes a temporary object, called the exception 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.
I think this gives rise to a very useful coding standard rule:
Base classes of an exception hierarchy should have a pure virtual destructor.
or
The copy constructor for a base class in an exception hierarchy shall be protected.
Either achieves the goal that the compiler will warn when you try to "throw e" since in the first case you cannot create an instance of an abstract class and the second because you cannot call the copy constructor.