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

Смутно о std:: runtime_error vs. std:: logic_error

Недавно я увидел, что библиотека boost_options boost выбрасывает logic_error, если вход в командную строку не был разбор. Это оспаривало мои предположения о logic_error vs. runtime_error.

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

Ответ 2

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

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

Ответ 3

В текущем черновике стандарта С++ 0x говорится (раздел 19.2):

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

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

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

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

Ответ 4

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

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

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

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

Ответ 5

ММО,

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

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