Подтвердить что ты не робот

Обнаружение при запуске деструктора из-за исключения исключения?

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

Ответ 3

Не делай этого, если у тебя нет веской причины. Распаковка стека - это такая языковая функция, что все автоматические объекты внутри блока 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 a resource leakage.
    }
    //..
  private:
    DB m_db;
};

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

Ответ 4

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

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