Archived

This topic is now archived and is closed to further replies.

kuphryn

Developing Custom Exception Handler :: C++

Recommended Posts

Hi. I would like to create a custom class exception handler. I want to use it for arbitrary exceptions that are not part of the exception library. I am having a problem with such a class. Here is the code for that exception class. ----- #ifndef CEXCEPTIONHANDLE_H #define CEXCEPTIONHANDLE_H class ExceptionHandle { public: ExceptionHandle(const char *error) : eMessage(error) {} const char *what() const throw() { return eMessage; } private: const char *eMessage; }; #endif ----- I basic want to *throw* a character string to the exception handle. Afterward, have a catch function to call what(). Here is an example of a try/catch. ---- try { function(x); } catch (ExceptionHandle *e) { cerr << e->what(); } ----- function(int X) { if (X == 0) throw ExceptionHandle("Error: X equals zero."); } ----- The program I am working on works, but it crashes whenever "throw ExceptionHandle("Error: X equals zero.");" occurs. Does anyone know what is wrong with my design and/or implementation? Thanks, Kuphryn

Share this post


Link to post
Share on other sites
The only idea I have is that your constructor should also be qualified as const throw(), just like your what() method.

On another note, though, you are supposed to inherit from std::exception. It makes your code better integrate with the STL and other applications that do not provide exception-specific handling (they can simply catch the base case).

#include <stdexcept>
#include <string>
//
// You should probably find a better name for this class too
class ExceptionHandle : public std::exception
{
public:
ExceptionHandle(const std::string error) const throw()
: m_err(error)
{
}
//
virtual cons char *what() const throw()
{
return m_err.c_str();
}
//
private:
std::string m_err;
};

You can also choose to implement more of the std::exception interface.

[ GDNet Start Here | GDNet Search Tool | GDNet FAQ | MS RTFM [MSDN] | SGI STL Docs | Google! ]
Thanks to Kylotan for the idea!

Share this post


Link to post
Share on other sites
maybe you should put
try
{
function(x)
}
catch(ExceptionHandle e)
{
cerr<}


If that doesn''t work, you could always debug with
try {
function(x);
}
catch(ExceptionHandle* e)
{
//did we catch an ExceptionHandle* ?
}
catch(unexpected_exception)
{
//are we throwing an unexpected exception?
}

Share this post


Link to post
Share on other sites
Okay. Thanks.

Visual C++ debugger kept point to the "throw" code as the source of the crash.

-----
throw ExceptionHandle("Error: X equals zero.");
-----

It pointed to that line. I did not add "const throw ()" to the constructor. I will try that tomorrow because I can barely open my eyes.

I''ll post an update.

Kuphryn

Share this post


Link to post
Share on other sites
Maybe I''m missing something obvious here ... but if you are using
catch (ExceptionHandle *e)

Shouldn''t you be using
throw new ExceptionHandle("Error: X equals zero.") ?

Share this post


Link to post
Share on other sites
Okay. Thanks.

I believe the problem was due to these pointer related calls:

-----
const char *eMessage
-----

and/or

-----
catch (ExceptionHandle *e)
-----

I will do two things.

1) I will replace "const char *eMessage" with "const string eMessage."
2) I will replace "catch (ExceptionHandle *e)" with "catch (ExceptionHandle &e)."

First, is the problem caused by "*e" pointing to something that no longer exists? How can that be if I am throwing an exception each time?

I can also add "new" to "throw...new" as Martee mentioned.

Which ones of these changes should *fix* the problem most elegantly?

Thanks,
Kuphryn

Edited by - kuphryn on February 20, 2002 10:11:38 AM

Share this post


Link to post
Share on other sites
Always catch exception by reference!

Reasons :

1. You do not need to call new and delete( because if you catch an exception and your program keeps going you will leak if you do not call delete on your exception. )

2. No slicing problems :
If you have hierarchy of classes for exceptions, and you only catch the base one by value, the destructor of the derived class won''t be correclty called and the overload what() functions also won''t be called.

ex.



class ExceptionBase
{
virtual char* what();
}

class DerivedException:public ExceptionBase
{
virtual char* what();
}

try
{
..

}
catch( ExceptionBase e)
{ std::cout << e.what() ; // uses exceptionBase.what() not DerivedException.what()

}



So always catch by refence!

Share this post


Link to post
Share on other sites
Never throw pointers. MFC did this and it just makes things a mess. Why burder your exception handler with the responsibility of deleting the exception object?

Exceptions are supposed to be slow, so do it the robust way: give your exception a good copy constructor and assignment operator, throw an object and catch a reference. If you need to change the exception, create a copy and throw that.

Also, you should definitely be deriving from the std::exception that most fits your error (runtime_error, logic_error, etc.) since your usage almost matches theirs exactly.

Share this post


Link to post
Share on other sites
Thanks.

I will catch exceptions via reference from now on. I am used to catching exceptions via value. The exception above is the first time I have tried catching one via pointer.

Kuphryn

Share this post


Link to post
Share on other sites
I made the follow changes.

-----
class ExceptionHandle : public exception
{
public:
ExceptionHandle(const std::string &error) : eMessage(error.c_str()) {}

virtual const char *what() const throw()
{
return eMessage.c_str();
}

private:
const std::string eMessage;
};
-----

...throw ExceptionHandle("...");

catch (ExceptionHandle &error)
{
cerr << error.what();
}

-----

I derived ExceptionHandle from class exception. bac_alloc is derived from exception too. Can I rely on ExceptionHandle to catch bac_alloc too?

For example, let say I use the class above in a try/catch. Is the follow right?

try
{...}

catch (exception::bad_alloc &error)
{
cerr << error.what();
}

Note that I am relying on the fact that ExceptionHandle is a derivative of class exception.

Kuphryn

Share this post


Link to post
Share on other sites