Exceptions in PCL

There have been a multitude of discussions in the past regarding exceptions in PCL (see http://www.pcl-developers.org/to-throw-or-not-to-throw-td4828759.html for an example). Herein, we discuss the major points with respect to writing and using exceptions.

Adding a new Exception

Any new exception should inherit from the PCLException class in pcl/exceptions.h

/** \class MyException
  * \brief An exception that is thrown when I want it.
  */

class PCL_EXPORTS MyException : public PCLException
{
  public:
    MyException (const std::string& error_description,
                 const char* file_name = NULL,
                 const char* function_name = NULL,
                 unsigned line_number = 0)
      : pcl::PCLException (error_description, file_name, function_name, line_number) { }
};

Using Exceptions

For ease of use we provide this macro

#define PCL_THROW_EXCEPTION (ExceptionName, message)
{
  std::ostringstream s;
  s << message;
  throw ExceptionName (s.str (), __FILE__, BOOST_CURRENT_FUNCTION, __LINE__);
}

Then in your code, add:

if (my_requirements != the_parameters_used_)
  PCL_THROW_EXCEPTION (MyException, "my requirements are not met " << the_parameters_used);

This will set the file name and the line number thanks to the macro definition. Take care of the message: it is the most important part of the exception. You can profit of the std::ostringstream used in the macro, so you can append variable names to variable values and so on to make it really explicit. Also something really important is when the method you are writing can throw an exception, please add this to the the function documentation:

/** Function that does cool stuff
  * \param nb number of points
  * \throws MyException
  */
void
myFunction (int nb);

This will be parsed by Doxygen and made available in the generated API documentation so the person that would use your function knows that they have to deal with an exception called MyException.

Exceptions handling

To properly handle exceptions you need to use the trycatch block.

// Here we call myFunction which can throw MyException
try
{
  myObject.myFunction (some_number);
  // You can put more exceptions throwing instruction within same try block
}
// We catch only MyException to be very specific
catch (pcl::MyException& e)
{
  // Code to deal with the exception maybe changing myObject.the_parameters_used_
}

// Here we catch any exception
#if 0
catch (exception& e)
{
  // Code to deal with the exception maybe changing myObject.the_parameters_used_
}
#endif

Exceptions handling is really context dependent so there is no general rule that can be applied but here are some of the most used guidelines:

  • exit with some error if the exception is critical

  • modify the parameters for the function that threw the exception and recall it again

  • throw an exception with a meaningful message saying that you encountered an exception

  • continue (really bad)