[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