[odb-users] Catch Exception Problem

Boris Kolpackov boris at codesynthesis.com
Thu May 30 12:03:52 EDT 2013


Hi Tarik,

Tarik BENZ <tenchu.tarik at hotmail.fr> writes:

> The problem is that this exception is not caught by my code.

All ODB exceptions derive from the odb::exception base, so if you
catch that (as you do in your code), then you should be catching
any ODB exception.


> template<typename Type> bool CreateNewObject(Type * object)
> {
>     if(object != NULL)
>     {
>         transaction * transact = NULL;
>         try
>         {
>             std::unique_ptr<odb::database> db (create_database());
>             transact  = new transaction (db->begin());
> 
>             // Make object persistent.
>             db->persist((*object));
>             transact->commit();
>         }
>         catch (const odb::exception& e)
>         {
>             cerr << e.what () << endl;
>             if(transact != NULL)
>             {
>                 transact->rollback();
>             }
>         }
>     }
>     return false;
> }

What can happen here is that the call to rollback() inside your
exception handler can throw. This is actually a good example of
how not to do it. Don't allocate the transaction object with new --
just allocate it on the stack. If it is destroyed before commit()
has been called (e.g., because an exception is thrown before you
got a chance to call commit()), then it will automatically roll
the transaction back. Also after certain failures (e.g., a connection
is lost) it is pointless to try to call rollback. ODB is smart
enough to handle that while your home-made auto-rollback is not.

So, if I had to reimplement your code, it would look like this:
  
template<typename Type> bool CreateNewObject(Type * object)
{
  if(object != NULL)
  {
    try
    {
      std::unique_ptr<odb::database> db(create_database());
      transaction t (db->begin());

      // Make object persistent.
      db->persist(*object);
      t.commit();

      return true;
    }
    catch (const odb::exception& e)
    {
      cerr << e.what () << endl;
    }
  }
  return false;
}

Just realized another problem in your code: the database instance
will no longer exist in the exception handler where you try to
rollback the transaction started on this database. And the exception
that you are unable to catch is most likely access violations.

Boris



More information about the odb-users mailing list