En lo que parece estar atrapado es en el infierno específico de alguien que trata de tener su pastel y comérselo también.
RAII y las excepciones están diseñadas para ir de la mano. RAII es el medio por el cual no tiene que escribir muchas catch(...)
declaraciones para realizar la limpieza. Sucederá automáticamente, por supuesto. Y las excepciones son la única forma de trabajar con objetos RAII, porque los constructores solo pueden tener éxito o lanzar (o poner el objeto en un estado de error, pero ¿quién quiere eso?).
Una catch
declaración puede hacer una de dos cosas: manejar un error o una circunstancia excepcional, o hacer un trabajo de limpieza. A veces hace ambas cosas, pero cada catch
declaración existe para hacer al menos una de estas.
catch(...)
es incapaz de hacer el manejo adecuado de excepciones. No sabes cuál es la excepción; No puede obtener información sobre la excepción. No tiene absolutamente ninguna otra información que no sea el hecho de que una excepción fue lanzada por algo dentro de un determinado bloque de código. Lo único legítimo que puedes hacer en ese bloque es hacer la limpieza. Y eso significa volver a lanzar la excepción al final de la limpieza.
Lo que RAII le brinda con respecto al manejo de excepciones es la limpieza gratuita. Si todo está encapsulado RAII correctamente, entonces todo se limpiará correctamente. Ya no necesita que las catch
declaraciones hagan la limpieza. En cuyo caso, no hay razón para escribir una catch(...)
declaración.
Así que estaría de acuerdo en que catch(...)
es mayormente malvado ... provisionalmente .
Esa disposición es el uso adecuado de RAII. Porque sin ella, necesita ser capaz de hacer cierta limpieza. No hay forma de evitarlo; tienes que poder hacer el trabajo de limpieza. Debes poder asegurarte de que lanzar una excepción dejará el código en un estado razonable. Y catch(...)
es una herramienta vital para hacerlo.
No puedes tener uno sin el otro. No se puede decir que tanto RAII como catch(...)
son malos. Necesita al menos uno de estos; de lo contrario, no estás a salvo de excepciones.
Por supuesto, hay un uso válido, aunque raro, catch(...)
que ni siquiera RAII puede desterrar: exception_ptr
enviar un mensaje a otra persona. Normalmente a través de una promise/future
interfaz o similar.
Mis compañeros de trabajo dicen que siempre debes saber qué excepciones se deben lanzar y que siempre puedes usar construcciones como:
Tu compañero de trabajo es un idiota (o simplemente terriblemente ignorante). Esto debería ser inmediatamente obvio debido a la cantidad de código de copiar y pegar que sugiere que escriba. La limpieza para cada una de esas declaraciones de captura será exactamente la misma . Esa es una pesadilla de mantenimiento, sin mencionar la legibilidad.
En resumen: este es el problema que RAII se creó para resolver (no es que no resuelva otros problemas).
Lo que me confunde acerca de esta noción es que generalmente es al revés de cómo la mayoría de las personas argumentan que RAII es malo. En general, el argumento dice "RAII es malo porque tienes que usar excepciones para señalar la falla del constructor. Pero no puedes lanzar excepciones, porque no es seguro y tendrás que tener muchas catch
declaraciones para limpiar todo". Lo cual es un argumento roto porque RAII resuelve el problema que crea la falta de RAII.
Lo más probable es que esté en contra de RAII porque oculta detalles. Las llamadas de destructor no son visibles inmediatamente en las variables automáticas. Entonces obtienes código que se llama implícitamente. Algunos programadores realmente odian eso. Aparentemente, hasta el punto en que piensan que tener 3 catch
declaraciones, todas las cuales hacen lo mismo con el código de copiar y pegar, es una mejor idea.
...
", Mientras que mi pregunta se centra en "¿Debería atrapar...
o<specific exception>
antes de volver a lanzar?"