Обнаружение, когда деструктор работает из-за исключения? - PullRequest
19 голосов
/ 22 августа 2011

Каков хороший способ в C ++ обнаружить в деструкторе, что он запускается при разматывании стека из-за генерируемого исключения в отличие от обычного выхода из области действия, запускающего деструктор? Я хотел бы знать, чтобы я мог создать класс, который имеет некоторый код очистки, который всегда запускается при нормальном выходе, но пропускается при возникновении исключения.

Ответы [ 4 ]

20 голосов
/ 22 августа 2011

std::uncaught_exception() (определено в <exception>) сообщит вам в деструкторе, вызван ли он из-за исключения:

class A
{
public:
    ~A()
    {
        if (std::uncaught_exception()) {
            // Called because of an exception
        } else {
            // No exception
        }
    }
};
5 голосов
/ 22 августа 2011

Вероятно эта статья поможет вам.Статья покажет вам проблемы с std :: uncaught_exception () и содержит советы, как обращаться с исключениями в деструкторах.

1 голос
/ 22 августа 2011

Не делайте этого, если у вас нет веских причин . Раскрутка стека - это такая языковая особенность, что все автоматические объекты внутри блока 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
  }
}
0 голосов
/ 22 августа 2011

Вот один из способов, который я могу придумать, но он кажется неуклюжим:

{
  myCleanupClass unwindAction;
  try {
    // do some work which may throw exception.
  } catch (...) {
    unwindAction.disableDestructorWork();
    throw;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...