Запутался насчет std :: runtime_error против std :: logic_error - PullRequest
43 голосов
/ 27 мая 2010

Я недавно видел, что библиотека boost program_options выдает logic_error, если ввод командной строки был не разбираем. Это оспорило мои предположения о logic_error против runtime_error.

Я предположил, что логические ошибки (logic_error и его производные классы) были проблемами, которые возникли в результате внутренних сбоев, связанных с программными инвариантами, часто в форме недопустимых аргументов для внутренних API. В этом смысле они в значительной степени эквивалентны ASSERT, но предназначены для использования в выпущенном коде (в отличие от ASSERT, которые обычно не компилируются в выпущенный код.) Они полезны в ситуациях, когда невозможно интегрировать отдельные программные компоненты в отладочные / тестовые сборки. или последствия сбоя таковы, что важно предоставить пользователю во время выполнения отзыв о недопустимом инвариантном условии.

Точно так же я думал, что runtime_error s возникли исключительно из-за условий выполнения вне контроля программиста: ошибки ввода-вывода, неверный ввод пользователя и т. Д.

Тем не менее, program_options явно интенсивно (главным образом?) Используются в качестве средства анализа ввода конечного пользователя, поэтому в моей ментальной модели он, безусловно, должен выдавать runtime_error в случае неправильного ввода.

Куда я иду не так? Согласны ли вы с расширенной моделью набора исключений?

Ответы [ 5 ]

31 голосов
/ 27 мая 2010

В этом случае я думаю (по крайней мере, по большей части), что вы правы, и это неправильно. Стандарт описывает logic_error как:

Класс logic_error определяет тип объектов, генерируемых как исключения для сообщений об ошибках, которые, вероятно, обнаруживаются до выполнения программы, например, при нарушениях логических предварительных условий или инвариантов класса.

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

В отличие от этого, он описывает runtime_error как:

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

Кажется, это лучше подходит.

8 голосов
/ 25 июня 2011

С чисто стандартной точки зрения вы правы.program_options должен выдавать классы, полученные из runtime_error или logic_error в зависимости от того, является ли ошибка во время выполнения или логической.(Я не просматривал текущий код, чтобы определить такую ​​классификацию идей для текущих исключений).

С практической точки зрения мне еще предстоит увидеть код C ++, который принимает полезные решения на основе того, является ли исключение logic_error или runtime_error.В конце концов, единственная причина, по которой вы бы выбросили logic_error вместо разрешения файла подтверждения, заключается в том, что вы хотите как-то попытаться восстановить, и это ничем не отличается от восстановления после ошибки времени выполнения.Лично я смотрю logic_error против runtime_error так же, как проверенные исключения в Java - теоретически хорошо, но на практике бесполезно.Это означает, что, может быть, я просто сделаю program_options::error производным от exception.То есть, когда я найду это «свободное время», о котором все будут говорить.

5 голосов
/ 28 мая 2010

В текущем проекте стандарта C ++ 0x сказано (пункт 19.2):

1) В модели ошибки, отраженной в эти классы (то есть типы исключений) ошибки делятся на две широкие категории: логические ошибки и ошибки во время выполнения.

2) Отличительная характеристика логических ошибок в том, что они обусловлены к ошибкам во внутренней логике программа. Теоретически они предотвратимый.

3) Напротив, ошибки времени выполнения обусловлены на события, выходящие за рамки программа. Они не могут быть легко прогнозируется заранее.

Вместе с кавычками, приведенными в одном из других ответов, это объясняет, почему Boost.ProgramOptions выдает std :: logic_error для предотвратимых ошибок, вызванных «ошибкой, предположительно обнаруживаемой до выполнения программы».

1 голос
/ 26 апреля 2013

Пользователь может проверить, что файл существует, запустить программу и внезапно узнать, что файл был удален. Вот почему проблема ввода / вывода всегда runtime_error. Проблемы с состоянием - это runtime_errors, даже если вызывающий мог проверить это, так как другой поток мог вызвать проблему.

logic_error - это когда аргументы функции неверны. только для вещей, которые могли быть обнаружены ранее при более строгой проверке типов.

Итак, «отсутствующий файл» - это runtime_error, а «неправильно отформатированный файл» - это logic_error.

Технически, логическая ошибка в функция тоже logic_error, но если вы достаточно умны, чтобы проверить ее внутри собственной функции, вы должны быть достаточно умны, чтобы предотвратить ее в первое место.

0 голосов
/ 29 апреля 2014

IMO,

  • std::logic_error генерируется программой C ++ пользователя логика преднамеренно. Предсказано пользовательской программой.

  • std::runtime_error генерируется средой выполнения C ++ (или основной частью языка ...) для абстрагирования ошибок более низкого уровня. Просто происходит без всякого намерения, без привлечения какого-либо пользовательского кода.

...