使用uncaught_exception来处理错误情况

时间:2011-12-07 16:02:04

标签: c++ exception-handling uncaught-exception

我有以下问题。

我有回收的数据库连接(放回池中)。

例如:

{
 session sql(conn_str); // take connection from pool

 sql.exec("insert into ...")
} // at the end of the scope return connection to pool

然而,在某些情况下,回收可能是错误的 - 例如断开连接或其他一些重大错误。

所以我想自动阻止连接被回收。我想要 使用std::uncaught_exception实现以下技术 - 所以exec()函数 会发现异常并阻止回收:

session::exec(...)
{
   guard g(this)

   real_exec(...);
}

守卫:

class guard {
public:
   guard(session *self) : self_(self) {}
   ~guard() {
      if(std::uncaught_exception()) {
        self->mark_as_connection_that_should_not_go_to_pool();
      }
   }
}

现在,我知道http://www.gotw.ca/gotw/047.htm不推荐使用 std::uncaught_exception在另一个案例中我也没有发现我的代码有任何问题, 提供了讨论的例子。

此代码是否存在任何问题。

注意:

  1. 我希望这个更改是非侵入性的,这样SQL后端就可以抛出而不检查每个案例是否很重要。
  2. 我不希望用户对此采取任何行动,因此对他来说是透明的。

1 个答案:

答案 0 :(得分:2)

我认为你的方法没有任何优势,而不是更简单:

session::exec()
{
    try
    {
        real_exec();
    }
    catch(...)
    {
        mark_as_connection_that_should_not_go_to_pool();
        throw;
    }
}

如果这个解决方案的冗长困扰你,我会注意到他们还没有从C ++中删除宏。我不喜欢这个版本,因为它掩盖了底层代码并且有点难看。

#define GUARD try {
#define ENDGUARD } catch(...) { mark_as_connection_that_should_not_go_to_pool(); throw; }

session::exec()
{
    GUARD
    real_exec();
    ENDGUARD
}

另一种可能性是假设失败直到成功。

session::exec()
{
    mark_as_connection_that_should_not_go_to_pool();
    real_exec();
    mark_as_connection_that_may_go_to_pool();
}

最后,为了回答uncaught_exception是否会按照您的概述工作的问题,我将引用Microsoft的功能文档:

  

特别是,当从异常展开期间调用的析构函数调用时, uncaught_exception 将返回 true

它似乎完全符合您的期望。