15-11-2003 09:05 assert() considered harmful
What’s wrong with this picture?
VideoSource videoSource(fileName);
const BYTE* frame;
Image image;

while (frame = vs.getFrame())
{
  assert(GrayscaleSerializer::Status::success == 
    GrayscaleSerializer::load(frame, image));
  processImage(image);
}

Разумеется.
#ifdef  NDEBUG
#define assert(exp)     ((void)0)
#else


Never write code with side effects inside a call to assert() (or something that might be one).
Herb Sutter, “Exceptional C++: 47 Engineering Puzzles, Programming Problems, and Solutions”, Item 47
Комментарии:
15-11-2003 18:37
Камрад
Заметки к теме.

I. Тем не менее, хотелось бы заметить, что использование своих подобных макросов улучшает читаемость кода: лучше делать проверку успешности с помощью макросов, нежели потом разбираться в конструкции if'ов. Например:

#define  ES_ASSERT(COND,RC)    do{if(!(COND)) return (RC);}while(0)
#define  ES_ASSERT_(COND)      do{if(!(COND)) return;}while(0)


void  ES_TileValidateRect( EIF_INTEGER aiHwnd,
                           EIF_POINTER alpRect)
{
   ES_ASSERT_(IsWindow((HWND)aiHwnd));
   ES_ASSERT_(ValidateRect((HWND)aiHwnd,(RECT*)alpRect));
}


Имеем следующее:
1) Поведение ES_ASSERT_ настраивается по мере надобностей: от игнорирования ошибки до аварийного выхода с выводом ругани в лог.
2) Результат более читаем, нежели последовательность стандартных проверок с помощью if

II. Использование assert крайне опасно при наследовании, так как произвольное изменение контракта приводит к нарушению сабтайпинга.
Вполне понятно, что для стабильной работы в переопределенном виртуальном методе наследника предусловия (проверка аргументов метода и состояния объекта и среды до вызова) можно только ослаблять, а постусловия (проверка состояния объекта и среды по окончании работы метода) - только усиливать. assert же, к сожалению, дает полную свободу.
15-11-2003 23:10
Камрад с блокнотиком
Я последнее время предпочитаю что-нибудь такое:
class xxxx_exception : public std::exception
{
  // здесь не особо интересно, скипнул
}

YYYY xxxxCheck(YYYY resultCode)
{
  if (failure_condition(resultCode))
  {
     throw xxxx_exception(f(resultCode));
  }
  return resultCode;
}

А дальше такое же hfile = handleCheck(CreateFile(…)), где failure_condition — сравнение с INVALID_HANDLE_VALUE, f сводится к GetLastError, а win32_exception::what вызывает FormatMessage с флагом FORMAT_MESSAGE_FROM_SYSTEM.

отредактировано: 15-11-2003 23:16 - Centaur

Закрыть