custom exception not always executing what() - c++

I'm starting to use exceptions and to handle more precisely some events or errors, I created my own type of exceptions derived from std::exception. So far everything went well but I've just noticed that sometimes the method what() does not print anything. The exception is well thrown and caught, but the explanation message print normally by the method what() does not always show on screen. It can happen with the same parameters as the previous execution which ended printing the message and seems to be completely random.
Here's my exceptions :
class MyException : public std::exception
{
public:
MyException() throw() {}
~MyException() throw() {}
virtual const char *what() const throw()
{
return "general exception\n";
}
};
class FileError : public MyException
{
public:
FileError(std::string nFileName) : MyException(), fileName(nFileName) { }
~FileError() throw (){ }
virtual const char *what()
{
std::ostringstream oss;
oss << "Error with file : \"" << fileName << "\"." << std::endl;
return (oss.str()).c_str();
}
protected:
std::string fileName;
};
and the context which cause me problem :
try
{
QFile sourceFile(sourceFileName);
if(!sourceFile.open(QIODevice::ReadOnly))
throw FileError(sourceFileName.toStdString());
sourceFile.close();
}
catch(FileError &e)
{
std::cout << "error file catch " << std::endl;
std::cout << e.what();
terminate();
}
"error file catch" is always print but "Error with file..." sometimes. Any idea what I'm doing wrong ? Thanks

You are returning a pointer to the contents of a temporary std::string.

You aren't flushing std::cout prior to calling terminate (assuming that is std::terminate). I would recommend using std::endl (which is a newline and a flush) at the point where it's output, and not inside FileError::what()
catch(FileError &e)
{
std::cout << "error file catch " << std::endl;
std::cout << e.what() << std::endl;
terminate();
}
Also, as pointed out by #Yuri Kilocheck, you're returning a pointer to a temporary string, invoking UB. The usual solution is to have a string member that is built when what() is executed (if there is a failure building the string, return some pre-defined version).

Related

How function-level exception handling works?

There is the following code, from here
class Base {
int i;
public:
class BaseExcept {};
Base(int i) : i(i) { throw BaseExcept(); }
};
class Derived : public Base {
public:
class DerivedExcept {
const char* msg;
public:
DerivedExcept(const char* msg) : msg(msg) {}
const char* what() const { return msg; }
};
Derived(int j) try : Base(j) {
// Constructor body
cout << "This won't print" << endl;
}
catch (BaseExcept&) {
throw DerivedExcept("Base subobject threw");;
}
};
int main() {
try {
Derived d(3);
}
catch (Derived::DerivedExcept& d) {
cout << d.what() << endl; // "Base subobject threw"
}
}
My question is, why the thrown exception is not caught here
catch (BaseExcept&) {
throw DerivedExcept("Base subobject threw");;
}
But the catch in main?
catch (Derived::DerivedExcept& d) {
cout << d.what() << endl; // "Base subobject threw"
}
Why does it output "Base subobject threw"
According to my understanding, the thrown exception should be caught in the catch after try (or the function body equivalent to try), but there is no, why?
What is the propagation path of the exception?
code from there
My question is this, try catch I have seen before all have this form.
try{}
catch(){}
So I think for the following snippet
Derived(int j) try: Base(j) {
// Constructor body
cout << "This won't print" << endl;
}
catch (BaseExcept&) {
throw DerivedExcept("Base subobject threw");;
}
When Derived() throws an exception, it should be caught by the catch (BaseExcept&)in the following line, not by the catch (Derived::DerivedExcept& d) in the main function.
But when I comment out it here
catch (Derived::DerivedExcept& d) {
//cout << d.what() << endl; // "Base subobject threw"
}
There will be no "Base subobject threw" output.
This is different from what I expected. I am learning basic exception knowledge. Did I understand something wrong
Derived(int j) try : Base(j) {
// Constructor body
cout << "This won't print" << endl;
}
catch (BaseExcept&) { // why the thrown exception is not caught here
throw DerivedExcept("Base subobject threw");;
}
The only way for the program to output Base subobject threw is if the exception is actually caught where you do not think it's caught. The string does not exist anywhere else in the program.
But the catch in main?
That's because you throw an exception in the catch. That exception is not caught by the same catch (which would result in infinite recursion in this case). It's caught by the outer try..catch which you have in main.

c++ destructor throw exception by single object

I'm trying to understand why throwing an exception from a destructor results in a program crash.
As I found many examples of two object which throw multiple exception and compiler can't handle multiple exception but in my case I only have a single exception thrown from the destructor. Why is my program still crashing?
class MyClass {
private:
string name;
public:
MyClass (string s) :name(s) {
cout << "constructor " << name << endl;
}
~MyClass() {
cout << "Destroying " << name << endl;
throw "invalid";
}
};
int main( )
{
try {
MyClass mainObj("M");
}
catch (const char *e) {
cout << "exception: " << e << endl;
cout << "Mission impossible!\n";
}
catch (...) {
cout << "exception: " << endl;
}
return 0;
}
Explanation from the MingW g++ compiler:
[P:\temp]
> g++ foo.cpp
foo.cpp: In destructor 'MyClass::~MyClass()':
foo.cpp:14:15: warning: throw will always call terminate() [-Wterminate]
throw "invalid";
^~~~~~~~~
foo.cpp:14:15: note: in C++11 destructors default to noexcept
To really let it throw you can do this:
~MyClass() noexcept(false){
Since C++11 destructors are implicitly declared as noexcept documentation
non-throwing functions are all others (those with noexcept specifier whose expression evaluates to true as well as destructors, defaulted special member functions, and deallocation functions)
emphasis is mine.

How to correctly implement my own exception handler in C++

I´m moving from C# to C++ so forgive me if the question is basic or has some misconceptions...
I want to build my own exception to be used on my try/catch blocks. I need to report a custom exception code, a custom exception message and a custom exception source origin - I may have all or some of these parameters.
So I´ve built that class:
CommonException.hpp
namespace exceptionhelper
{
class CommonException : public std::exception {
public:
CommonException();
CommonException(std::string message);
CommonException(std::string source, std::string message);
CommonException(int code, std::string source, std::string message);
virtual ~CommonException();
const char *what() const throw();
private:
int exceptionCode;
std::string exceptionSource;
std::string exceptionMessage;
};
}
And the implementation:
CommonException.cpp
namespace exceptionhelper {
CommonException::CommonException() {
exceptionCode = 0;
exceptionMessage = "No message.";
exceptionSource = "No source.";
}
CommonException::CommonException(std::string message) {
exceptionCode = 0;
exceptionMessage = message;
exceptionSource = "No source.";
}
CommonException::CommonException(std::string source, std::string message) {
exceptionCode = 0;
exceptionMessage = message;
exceptionSource = source;
}
CommonException::CommonException(int code, std::string source, std::string message) {
exceptionCode = code;
exceptionMessage = message;
exceptionSource = source;
}
CommonException::~CommonException() {
}
const char *CommonException::what() const throw()
{
std::stringstream s;
s << "Code : " << exceptionCode << std::endl;
s << "Source : " << exceptionSource << std::endl;
s << "Message : " << exceptionMessage << std::endl;
return s.str().c_str();
}
}
And finally my implementation:
main ()
{
try {
... code ...
throw new CommonException(10, "here", "test exception");
}
catch (const std::exception &exc)
{
std::cerr << "Exception detected:" << std::endl;
std::cerr << exc.what();
}
catch (...)
{
std::cerr << "Unknown exception called." << std::endl;
throw;
}
}
For some reason I´m getting this result:
Unknown exception called.
terminate called after throwing an instance of 'linuxcommon::exceptionhelper::CommonException*'
Aborted (core dumped)
Questions:
a) Why am I not catching my custom exception ?
b) I´m pretty sure there are better ways to do this exception handling, but I cannot figure that out yet...
Thanks for helping...
Some notes for your code.
You may want to derive your exception class from std::runtime_error (instead of std::exception), since std::runtime_error already provides a constructor with an error message string.
Of course you can add your own exception's data members to the derived class.
You don't need to define a virtual destructor with an empty body for your exception class, since you don't have explicit cleanup code to execute. std::exception has a virtual destructor, and that will work just fine for your derived exception class.
You can use a more idiomatic C++ syntax to initialize your exception data members in constructors, e.g. instead of:
CommonException::CommonException() {
exceptionCode = 0;
exceptionMessage = "No message.";
exceptionSource = "No source.";
}
you can use:
CommonException::CommonException()
: exceptionCode(0),
exceptionMessage("No message."),
exceptionSource("No source.")
{ }
If you pass string parameters, you can still pass by value, but you may want to std::move() from the value to initialize data members, e.g. instead of:
CommonException::CommonException(std::string source, std::string message) {
exceptionCode = 0;
exceptionMessage = message;
exceptionSource = source;
}
You can do:
CommonException::CommonException(std::string source, std::string message)
: exceptionCode(0),
exceptionMessage(std::move(message)),
exceptionSource(std::move(source))
{
}
Consider making your single-string-argument constructor explicit, to prevent bogus implicit conversions from strings to exceptions:
explicit CommonException(std::string message);
In its current form, your what() method implementation can throw, because inserting operations (<<) on std::stringstream can throw:
const char *CommonException::what() const throw()
{
std::stringstream s;
s << "Code : " + exceptionCode << std::endl;
s << "Source : " + exceptionSource << std::endl;
s << "Message : " + exceptionMessage << std::endl;
return s.str().c_str();
}
So, remove the throw() specification, making it simply:
const char* CommonException::what() const
(As a side note, the modern C++11 way of marking a method as non-throwing is using noexcept).
You may also want to simply use '\n' instead of std::endl to avoid premature pessimization.
Moreover, you are returning in this line a temporary string:
return s.str().c_str();
The const char* pointer returned to the caller will just point to some garbage at the call site: this introduces a bug.
To fix that, you may want to consider adding a std::string data member, format the whole error message string inside that data member during exception object construction (i.e. in your constructors - you may also build a private helper method to do that, to avoid repeating code in each constructor), and just return m_str.c_str() from the what() method.
If you derive your exception class from std::runtime_error, you can just build the whole error message string at construction time, and pass that to std::runtime_error's constructor. In this case, std::runtime_error::what() will Do The Right Thing, and you won't need to override what() in your exception class.
E.g.
// Derive from std::runtime_error instead of std::exception
class CommonException : public std::runtime_error
...
CommonException::CommonException( /* your exception data */ )
: std::runtime_error(BuildErrorMessage( /* your exception data */ )
{ }
// Private helper method
std::string CommonException::BuildErrorMessage( /* your exception data */ )
{
// Build your exception message string here,
// e.g. you can use std::ostringstream here,
// and just call its str() method
// to return the whole error message string.
...
}
At the exception's "client" side, you have:
... code ...
throw new CommonException(10, "here", "test exception");
}
catch (const std::exception &exc)
Instead, consider throwing by value, instead of dynamically allocating the exception object on the heap, e.g. simply do:
throw CommonException( /* your exception data*/ );

How do I use boost's set_exception_handler?

I want to set a global exception handler in C++. With a hook, any exceptions (of a specified type) thrown, would be caught by the handler. With this, I could do a little pretty printing before the exception kills the program, or maybe I could write everything to a log file.
boost seems to have an exception handler hook. This seemed extremely promising, but the code provided didn't work as I thought it should. Am I missing something?
struct my_handler
{
typedef void result_type;
void operator() (std::runtime_error const& e) const
{
std::cout << "std::runtime_error: " << e.what() << std::endl;
}
void operator() (std::logic_error const& e) const
{
std::cout << "std::logic_error: " << e.what() << std::endl;
throw;
}
};
void init_exception_handler()
{
// Setup a global exception handler that will call my_handler::operator()
// for the specified exception types
logging::core::get()->set_exception_handler(logging::make_exception_handler<
std::runtime_error,
std::logic_error
>(my_handler()));
}
// The above is all code from the boost doc example. Untouched.
int main(int argc, char* argv[]) {
init_exception_handler();
// I can throw now right...?
throw std::runtime_error("This should be suppressed!");
return 0;
}
In this code, the runtime_error I throw is not suppressed even though I thought I had setup the exception handler.

catching std::exception by reference?

I have a silly question. I read this article about std::exception http://www.cplusplus.com/doc/tutorial/exceptions/
On catch (exception& e), it says:
We have placed a handler that catches exception objects by reference (notice the ampersand & after the type), therefore this catches also classes derived from exception, like our myex object of class myexception.
Does this mean that by using "&" you can also catch exception of the parent class? I thought & is predefined in std::exception because it's better to pass e (std::exception) as reference than object.
The reason for using & with exceptions is not so much polymorphism as avoiding slicing. If you were to not use &, C++ would attempt to copy the thrown exception into a newly created std::exception, potentially losing information in the process. Example:
#include <stdexcept>
#include <iostream>
class my_exception : public std::exception {
virtual const char *what() const throw() {
return "Hello, world!";
}
};
int main() {
try {
throw my_exception();
} catch (std::exception e) {
std::cout << e.what() << std::endl;
}
return 0;
}
This will print the default message for std::exception (in my case, St9exception) rather than Hello, world!, because the original exception object was lost by slicing. If we change that to an &:
#include <stdexcept>
#include <iostream>
class my_exception : public std::exception {
virtual const char *what() const throw() {
return "Hello, world!";
}
};
int main() {
try {
throw my_exception();
} catch (std::exception &e) {
std::cout << e.what() << std::endl;
}
return 0;
}
Now we do see Hello, world!.
Does this mean that by using "&" you can also catch exception of the parent class?
No, this doesn't increase the scope of where you will catch exceptions from (e.g. from the parent class of the class that contains the try/catch code).
It also doesn't increase the types of exceptions that can be caught, compared to catching by value (catch(std::exception e) without the & - you'll still catch each exception that either is std::exception or derives from it).
What it increases is the amount of data that you will actually get when you catch the exception.
If an exception is thrown that derives from std::exception, and you catch it by value, then you are throwing out any extra behavior in that exception class. It breaks polymorphism on the exception class, because of Slicing.
An example:
class MyException : public std::exception
{
public:
virtual const char* what() const
{
return "hello, from my exception!";
}
};
// ...
try
{
throw MyException();
}
catch(std::exception& e)
{
// This will print "hello, from my exception!"
std::cout << e.what() << "\n";
}
// ...
try
{
throw MyException();
}
catch(std::exception e)
{
// This will print "Unknown exception"
std::cout << e.what() << "\n";
}
No the & has absolutely no bearing on the polymorphic nature of exception handlers. Their wording is very poor, it does seem to indicate that the & is somehow responsible. This is not the case. You are correct, & just passes by reference which is a tad more efficient.
Also as a general rule, you should really try to avoid cplusplus.com.
Updated link: What's wrong with cplusplus.com
Using reference to exception here can reduce the temporary objects created, and it can also keep the polymorphism.