2010-05-27 30 views
39

Recientemente vi que la biblioteca impulsar program_options lanza un logic_error si la entrada de la línea de comandos no se pudo analizar. Eso desafió mis suposiciones sobre logic_error contra runtime_error.Confundido sobre std :: runtime_error contra std :: logic_error

Supuse que los errores lógicos (logic_error y sus clases derivadas) eran problemas que resultaban de fallas internas para adherirse a las invariantes del programa, a menudo en forma de argumentos ilegales para las API internas. En ese sentido, son en gran parte equivalentes a ASSERT, pero destinados a ser utilizados en código liberado (a diferencia de ASSERT, que generalmente no se compilan en código publicado). Son útiles en situaciones donde no es factible integrar componentes de software separados en compilaciones de depuración/prueba o las consecuencias de una falla son tales que es importante dar retroalimentación en tiempo de ejecución sobre la condición invariable no válida para el usuario.

mismo modo, pensé que runtime_error s dieron como resultado exclusivamente de las condiciones de tiempo de ejecución fuera del control del programador: errores de E/S, la entrada de usuario no válido, etc.

Sin embargo, program_options es, obviamente, muy usado (principalmente?) como un medio para analizar la entrada del usuario final, entonces bajo mi modelo mental ciertamente debería arrojar un runtime_error en el caso de una mala entrada.

¿Dónde me estoy equivocando? ¿Estás de acuerdo con el modelo de impulso del tipeo de excepciones?

+1

¿Por qué no hace esta pregunta en la lista de correo de los usuarios de impulso? –

Respuesta

30

En este caso, creo (al menos en su mayor parte) tienes razón y está mal. La norma describe logic_error como:

El logic_error clase define el tipo de objetos lanzados como excepciones para informar de errores presumiblemente detectables antes de ejecuta el programa, tales como violaciónes de condiciones previas lógicas o invariantes de clase.

Un argumento de línea de comandos que no se puede analizar no parece encajar muy bien.

Por el contrario, describe runtime_error como:

El runtime_error clase define el tipo de objetos arrojados como excepciones para informar de errores presumiblemente detectable sólo cuando el programa se ejecuta.

Ese parece ser un mejor ajuste.

5

El proyecto actual de la 0x Standard C++ dice (cláusula 19.2):

1) En el modelo de error refleja en estas clases (es decir, los tipos de excepciones), los errores se dividen en dos categorías amplias: errores de lógica y errores de tiempo de ejecución .

2) La característica distintiva de errores de lógica es que son debido a errores en la lógica interna del programa . En teoría, son prevenibles.

3) Por el contrario, los errores de tiempo de ejecución se deben a a eventos fuera del alcance del programa . No pueden ser fácilmente pronosticados de antemano.

Junto con las cotizaciones citadas en una de las otras respuestas Esto explica por qué Boost.ProgramOptions lanza un std :: logic_error de errores evitables causadas por un 'error de suponer detectable antes de que el programa se ejecuta'.

+0

Según su lógica, si el usuario pasó un argumento que contiene una ruta a un archivo inexistente, la aplicación arrojará un error lógico en respuesta al error de tiempo de ejecución del archivo no encontrado desde el argumento de la aplicación, creado antes del la aplicación comenzó, era probablemente incorrecta. No compro eso. –

+0

Bueno, en realidad no es mi lógica. Te di citas del Estándar. Obviamente, no hay un posible destino entre ambos tipos de errores, y la entrada incorrecta del usuario es una de esas "zonas grises". – hkaiser

+0

Esto giraría sobre si se puede esperar razonablemente que el programa verifique/desinfecte el tipo de entrada relevante. Si tal expectativa no es razonable, está más allá del alcance del programa. Pero el "alcance" se define como las expectativas del código de la biblioteca, no el diseño de su programa. – Grault

8

Desde el punto de vista del estándar puro, tiene razón. program_options debe lanzar clases derivadas de runtime_error o logic_error dependiendo de si el error es en tiempo de ejecución o lógico. (No revisé el código actual para determinar dicha clasificación de idea para las excepciones actuales).

Desde un punto de vista práctico, aún no he visto el código C++ que toma decisiones útiles en función de si la excepción es logic_error o runtime_error. Después de todo, la única razón por la que arrojaría un logic_error en lugar de dejar que afirme el archivo es si desea intentar recuperar de alguna manera, y eso no es diferente de la recuperación de un error de tiempo de ejecución. Personalmente, veo logic_error frente a runtime_error de la misma manera que las excepciones comprobadas en Java: teóricamente agradable, pero no útil en la práctica. Lo que significa que, tal vez, haré que program_options::error derive de exception. Es decir, cuando encuentre ese "tiempo libre", todo el mundo sigue hablando.

+2

Creo que debe dejar que el logic_error vaya y termine el programa (para que la víctima pueda enviar la información de depuración/núcleo a los desarrolladores), mientras que runtime_error debe ser capturado e informar: "me dio información no analizable, intente de nuevo." –

1

El usuario puede verificar que el archivo existe, ejecutar el programa y, de repente, saber que el archivo se ha eliminado. Es por eso que un problema de E/S siempre es un runtime_error. Los problemas de estado son runtime_errors, incluso si la persona que llama pudo haber verificado, ya que otro hilo podría causar el problema.

logic_error es cuando los argumentos para una función son incorrectos. Es solo para cosas que podrían haber sido detectadas anteriormente con una verificación de tipo más fuerte.

Por lo tanto, "archivo faltante" es un runtime_error, pero "nombre de archivo formateado incorrectamente" es un logic_error.

Técnicamente, un error lógico dentro de una función es un logic_error también, pero si usted es lo suficientemente inteligente como para probar que dentro de su propia función, que debe ser lo suficientemente inteligente como para evitar que en el primer lugar.

+0

"si es lo suficientemente inteligente como para probarlo dentro de su propia función, debe ser lo suficientemente inteligente como para evitarlo en primer lugar" - esto hace un montón de suposiciones, incluyendo que usted tiene el control de todo el código – minexew

+0

Hay 3 dominios: 1) la persona que llama de su función, 2) su función, y 3) las bibliotecas llamadas por su función. Si (1) llama (2) con una entrada incorrecta, (2) debería lanzar 'logic_error'. Si algo salió mal que (1) no pudo probar (por ejemplo, un archivo se borró de repente por otro proceso), (2) debería lanzar 'runtime'. Eso está claro, ¿verdad? ¿Pero qué sucede si (2) llama (3) incorrectamente? Ese es un error lógico causado por (2), por lo que (3) podría arrojar 'lógica'. Estoy diciendo que si (2) atrapa una 'lógica' lanzada por (3), (2) debería relanzarse como 'tiempo de ejecución', pero es mejor no causar el error en primer lugar. – cdunn2001

0

OMI,

  • std::logic_error es lanzada por un programa lógica intencionalmente usuario C++. Predicho por un programa de usuario.

  • std::runtime_error es lanzada por un tiempo de ejecución C++ (o parte central del langauge ...) a los errores abstractos de nivel inferior. Simplemente sucede sin ninguna intención sin la participación de ningún código de usuario.

Cuestiones relacionadas