Исключения: использование макросов MFC и исключений C++

Замечание

Библиотека классов Microsoft Foundation (MFC) продолжает поддерживаться. Однако мы больше не добавляем функции или обновляем документацию.

В этой статье рассматриваются рекомендации по написанию кода, использующего макросы обработки исключений MFC и ключевые слова обработки исключений C++.

В этой статье рассматриваются следующие разделы:

Сочетание ключевых слов исключений и макросов

Макросы исключений MFC и ключевые слова исключений C++ можно смешивать в той же программе. Но нельзя смешивать макросы MFC с ключевыми словами исключений C++ в одном блоке, так как макросы автоматически удаляют объекты исключений при выходе из области видимости, в то время как код с использованием ключевых слов обработки исключений этого не делает. Дополнительные сведения см. в статье "Исключения: перехват и удаление исключений".

Основное различие между макросами и ключевыми словами заключается в том, что макросы "автоматически" удаляют пойманные исключения, когда исключение выходит из области. Код, использующий ключевые слова, не имеет; Исключения, пойманные в блоке catch, должны быть явно удалены. Сочетание макросов и ключевых слов исключений C++ может привести к утечке памяти, если объект исключения не удаляется, или повреждение кучи при удалении исключения дважды.

Приведенный ниже код, например, делает указатель исключения недействительным.

TRY
{
   TRY
   {
   // Do something to throw an exception.
   AfxThrowUserException();
}
CATCH(CException, e)  // The "inner" catch block
{
   throw;  // Invalid attempt to throw exception
         // to the outer catch block below.
}
END_CATCH
}
CATCH(CException, e)  // The "outer" catch block
{
   // Pointer e is invalid because
   // it was deleted in the inner catch block.
}
END_CATCH

Проблема возникает из-за удаления e, когда выполнение выходит из 'внутреннего' блока CATCH. Использование макроса THROW_LAST вместо инструкции THROW приведет к тому, что внешний блок CATCH получит действительный указатель:

TRY
{
   TRY
   {
   // Do something to throw an exception.
   AfxThrowUserException();
}
CATCH(CException, e)  // The "inner" catch block
{
   THROW_LAST(); // Throw exception to the outer catch block below.
}
END_CATCH
}
CATCH(CException, e)  // The "outer" catch block
{
   // Pointer e is valid because
   // THROW_LAST() was used.
}
END_CATCH

Попробовать блоки внутри блоков catch

Вы не можете повторно выбросить текущее исключение из блока try, который находится внутри блока CATCH. Следующий пример недопустим:

TRY
{
   // Do something to throw an exception.
   AfxThrowUserException();
}
CATCH(CException, e)
{
   try
   {
      throw;  // Wrong.  Causes e (the exception 
            // being thrown) to be deleted.
   }
   catch (CException* exception)
   {
      exception->ReportError();
   }
}
END_CATCH

Дополнительные сведения см. в разделе "Исключения: изучение содержимого исключений".

См. также

обработка исключений