检测析构函数因抛出异常而运行的时间?

时间:2011-08-22 01:16:41

标签: c++ exception destructor raii

在C ++中有什么好方法可以在析构函数中检测它是否在堆栈展开期间运行,因为抛出异常而不是正常退出触发析构函数的作用域?我想知道,以便我可以创建一个具有一些清理代码的类,该代码始终在正常退出时运行,但在发生异常时跳过。

4 个答案:

答案 0 :(得分:19)

std::uncaught_exception()(在<exception>中定义)将在析构函数中告诉您是否因为异常而被调用:

class A
{
public:
    ~A()
    {
        if (std::uncaught_exception()) {
            // Called because of an exception
        } else {
            // No exception
        }
    }
};

答案 1 :(得分:5)

可能this文章会对您有所帮助。本文将向您展示std :: uncaught_exception()的问题,并包含如何处理析构函数中的异常的建议。

答案 2 :(得分:1)

除非你有充分的理由,否则不要这样做。堆栈展开是一种语言特性,try块中的所有自动对象都将被强制解除分配,以便它们内部的资源有机会释放。

您希望在堆栈展开期间在dtor中跳过清理,这会绕过它的初衷。而你将面临资源泄漏的风险。

示例

class CDBConnection
{
  public:
    CDBConnection()
    {
      m_db.open();
    }
    ~CDBConnection()
    {
      if (!std::uncaught_exception())
        m_db.close();

      // if this is called during a stack unwinding,
      // your DB connection will not be closed for sure.
      // That's a resource leakage.
    }
    //..
  private:
    DB m_db;
};

void main()
{
  //..
  try
  {
    // code that may throw
    CDBConnection db;
    //..        
  }
  catch(const CDBException& exp)
  {
    // properly handle the exception
  }
}

答案 3 :(得分:0)

这是我能想到的一种方式,但它似乎很笨拙:

{
  myCleanupClass unwindAction;
  try {
    // do some work which may throw exception.
  } catch (...) {
    unwindAction.disableDestructorWork();
    throw;
  }
}