[geos-devel] GEOSException is incompatible with std::exception
Mateusz Łoskot
mateusz at loskot.net
Mon Apr 3 18:09:59 EDT 2006
Hi,
GEOSException class and all its derivatives is incompatible with
std::exception.
GEOSException is derived from std::exception but it does not make much
sense. It even introduces many confusions.
GEOSException has its own member to store message GEOSException::txt.
But std::exception has it's own member storing exception message.
It also has it's own version of what() function that returns
GEOSException::txt but this what() has nothing to do with that one
provided by std::exception.
The main problem is that exception details are not available through
std::exception interface.
Simply, this structure is a kind of two types in one, but every of this
participator is completely separated from another one.
Here is illustration of the problem:
try
{
throw geos::util::GEOSException("This is a message from GEOS.");
}
catch (std::exception const& e)
{
std::string msg = e.what();
std::cout << msg << std::endl; <--- BUM! BUM! BUM!
}
In the example above, exceptions are catched through base
std::exception. It's very common situation.
The problem is that e.what() returns null pointer.
std::exception member of string message is not initialized during
construction of GEOSException. This is a bug.
This example illustrates that deriving GEOSException from std::exception
has no effect at all. std::exception type is completely unused.
My suggestions are:
1. To remove GEOSException::txt
2. To use std::exception buffer member for message (in VC++ version of
STL it's private member std::exception::_m_what declared as:
const char *_m_what;
3. To initialize call base class (std::exception) constructor during
construction of GEOSException using initializers list:
class GEOSException : public std::exception
{
public:
GEOSException(char const* msg) : std::exception(msg) {}
GEOSException(std::string const& msg)
: std::exception(msg.c_str())
{}
virtual ~GEOSException() {}
};
4. Use initializers list in every class derived from GEOSException,
so every time std::exception's message member will be initialized.
Here is usage example that proofs it fixes the problem I introduced:
///////////////////////////////////////////////////////////
#include <iostream>
#include <string>
#include <exception>
class GEOSException : public std::exception
{
public:
GEOSException(char const* msg) : std::exception(msg) {}
GEOSException(std::string const& msg)
: std::exception(msg.c_str())
{}
virtual ~GEOSException() {}
};
int main()
{
try
{
throw GEOSException("This is a message from GEOS.");
}
catch (std::exception const& e)
{
std::string msg = e.what();
std::cout << msg << std::endl;
}
try
{
std::string msg("This is a std::string message from GEOS.");
throw GEOSException(msg);
}
catch (std::exception const& e)
{
std::string msg = e.what();
std::cout << msg << std::endl;
}
return 0;
}
///////////////////////////////////////////////////////////
Cheers
--
Mateusz Łoskot
http://mateusz.loskot.net
More information about the geos-devel
mailing list