¿Es la garantía de seguridad de excepción fuerte con un argumento de paso por valor que puede provocar la destrucción posible?

8

Suponga que tiene un tipo con un destructor de lanzamiento y una función que lo recibe por valor.
¿Puede esa operación ofrecer algo mejor que la garantía de excepción básica?
O formulado de manera diferente, ¿se puede ignorar la destrucción del argumento que se pasó por valor al determinar si una operación tiene semántica de commmit-and-rollback?

#include <cstdlib>

struct X {
    ~X() noexcept(0) {
        if(rand()%6 == 0) throw 0;
    }
    // some state
};

void update(database db, X arg) noexcept;

X x;
update(db, x);

Personalmente, basado en la definición de wikipedia

  1. Fuerte excepción de seguridad , también conocida como semántica de confirmación o reversión : las operaciones pueden fallar, pero se garantiza que las operaciones fallidas no tendrán efectos secundarios, por lo que todos los datos conservan sus valores originales

No creo que sea útil describir update como altamente seguro para excepciones, aunque la función en sí misma ni siquiera puede lanzar.

Agradecería que alguien me mostrara la locura de mi comprensión actual o que diera un mejor argumento.

Deduplicador
fuente
¿Qué pasa si un método en la clase arroja y la persona que llama decide deshacerse del objeto? ¿El destructor seguirá cerrando la transacción?
Robert Harvey
Método en qué clase? ¿Y cerrar qué transacción? Lo siento, pero ahora estoy confundido.
Deduplicador
Bueno, a menos que se esté utilizando un patrón de recuerdo, o que esté involucrada una transacción de base de datos, no veo cómo el estado de la clase no se pierde cuando se desecha el objeto, a menos que esté diciendo que es una clase sin estado.
Robert Harvey
2
La pregunta se inspira en la discusión aquí: chat.stackexchange.com/rooms/32049/... chat.stackexchange.com/rooms/32061/...
Deduplicator
44
En general, un destructor de lanzamiento es un veneno completo para todas las garantías de seguridad de excepción. Simplemente se vuelve más difícil por órdenes de magnitud.
Sebastian Redl

Respuestas:

7

No estoy realmente seguro en retrospectiva, pero si updateera genérico o si Xera abstracto (por ejemplo: clonado y destruido), es decir, si updateno pudiera saber nada concreto sobreX , entonces, a todos los efectos prácticos, lo describiría como un fuerte Garantía de seguridad de excepción. Como mínimo, eso es lo más cercano a una fuerte garantía de seguridad de excepción que jamás obtendrá en un contexto abstracto sin rayos X de un tipo de datos.

Sin embargo, Xes concreto, lo que hace que esta pregunta sea mucho más confusa. Todavía estoy tentado a decir esoupdate "tiene una fuerte garantía de seguridad de excepción", ya que está haciendo todo lo posible para hacerla cumplir. ¿Suena como una locura? Lo hace para mí, pero realmente no puedo decirlo mucho mejor.

Especialmente en el contexto de un entorno de equipo donde un autor implementa updatey el otro implementa X, nada podría proporcionar una fuerte garantía de seguridad de excepción, ya que Xpodría modificarse de manera que rompa la garantía de formas completamente fuera del control de update. Para fines prácticos, creo que siupdate hace todo lo posible y puede hacer retroceder sus propios efectos secundarios en caminos excepcionales, prácticamente proporciona una fuerte garantía de seguridad de excepción.

De lo contrario, la fuerte garantía de seguridad de excepción se convierte en algo poco práctico que ofrecer en tantos escenarios. Las cosas podrían cambiar fuera del control de la función. Las cosas podrían ser abstractas en formas más allá del conocimiento de la función. La garantía total sería casi imposible de proporcionar en cualquier lugar. En ese caso, ¿podríamos decir que la fuerte garantía de excepción updatepropaga la responsabilidad Xde cumplir, o updatees necesario saber cómo Xse implementará en todo momento? No lo sé. Todo esto es muy poco práctico de cualquier manera, y no me gustan las impracticabilidades.

Así que voy a ir con el crudo, sí, " updatees seguro para las excepciones, pero se Xvolvió fubar y estropeó todo. No es update'sculpa al menos. ¡No demandes al autor de la actualización! ¡Sue al autor de X!" . Me gustaría describir Xcomo simplemente ser fubar aquí, y updateposiblemente proporcionar una fuerte garantía de seguridad de excepción que se ve afectada por el hecho de que Xes fubar. Es decir, a menos que haya una comprensión de nivel de interfaz muy difícil que el X'sdestructor está diseñado para lanzar, en cuyo caso no tengo idea de cómo describirlo, excepto como un "gran problema". Creo que necesitamos algunas letras pequeñas y renuncias de responsabilidad con estas garantías.La actualización ofrece una fuerte garantía de seguridad de excepción siempre que [...]. No hay reembolsos si este no es el caso!

Esto es como una pregunta filosófica para mí, interesante de pensar pero quizás una sin respuesta perfecta. ¿Y qué son las garantías de todos modos? ¿Podemos garantizar algo? Podría garantizar que beber cerveza me emborracharía y eso podría parecer cierto todo el tiempo, pero ¿qué pasa si un extraterrestre interviene y usa algún tipo de tecnología alienígena que me pone sobrio sin importar cuánto bebo? No puedo garantizarque esto no sucederá Solo puedo decir que esto es altamente improbable y que si tal evento ocurriera, sería impotente contra él. Hice mi parte Bebí mi cerveza Se supone que debo emborracharme. Lo garantizo fuertemente. Pero no es seguro. Siempre hay alguna probabilidad, aunque astronómicamente remota, de que la garantía no sea cierta. ¿Qué tal la seguridad del hilo? Bueno, ¿qué pasa si la nave extraterrestre viene y destruye nuestro hardware y reorganiza las instrucciones en la memoria de modo que una función que no sea segura para subprocesos ya no es segura para subprocesos en tiempo de ejecución? No puedo garantizar que esto no suceda. Pero garantizaré la seguridad del hilo sin tener que escribir ni siquiera una letra pequeña sobre las naves espaciales alienígenas, porque hace que la gente se sienta agradable y tranquilizada, y lo que digo es que yo '

Descartes dijo una vez: "Creo, por lo tanto, que soy". ¿Cómo lo sabe él? ¿Y si no lo es? Él podría ser un "no soy" pero quizás los "no" pueden "pensar". Ni siquiera sé si existo. ¿Qué significa pensar incluso de todos modos? Es como una palabra que la gente usa para describir un proceso que parece continuar de manera introspectiva y parece que nosotros, que ni siquiera existimos, estamos tomando decisiones.

¿Qué pasa si todos somos bits y bytes en alguna máquina? Como esa rubia o morena en Matrix. Por cierto, ¿cómo se puede almacenar una rubia o especialmente una morena en un flujo tan pequeño de personajes? ¿Son como UTF2048? Era una especie de corriente alienígena de personajes, pero no parecía haber demasiados personajes únicos. Quizás es algún tipo de llamada a la función. De todos modos, no estoy seguro de que podamos garantizar nada. Todo es relativo a lo que creemos que es verdad.


fuente
55
"Entonces, la" seguridad de excepción "de cualquier tipo y el" destructor de lanzamiento "probablemente nunca deberían combinarse en la misma oración. Son, para todos los propósitos prácticos, mutuamente excluyentes". +1, no puedo discutir con esa lógica. Si crees que puedes, no estás siendo lógico.
No veo cómo esto responde la pregunta original. El problema aquí es que arg destruirá exactamente al salir de la función. La función no tendrá oportunidad de atrapar esto. Si la función ha hecho algo, no tendrá la oportunidad de revertirla.
Nir Friedman
2
Sí, esa es la conclusión correcta, no se vuelve menos correcto por ser desagradable. En el caso del vector, es ilegal que contenga el destructor de tipo contenido: stackoverflow.com/questions/26902006/… . Entiendo su enfoque "orientado al equipo", pero, francamente, lo está mirando desde una perspectiva de justicia y no de corrección.
Nir Friedman
2
Mi interpretación preferida es simplemente que arrojar un destructor es un comportamiento indefinido, y qué excepción garantiza que una función se basa en el supuesto implícito de que no ocurre un comportamiento indefinido (de hecho, todo en el lenguaje hace esa suposición). Si el comportamiento indefinido puede incluir formatear su disco duro, ciertamente puede incluir violar las garantías de excepción de lo contrario correctas de todo lo demás en el programa.
Ixrec
1
@Ixrec Esa puede ser su interpretación preferida, pero lanzar desde un destructor no es ub en general, eso es simplemente un hecho.
Nir Friedman
-1

Técnicamente hablando, tal vez pueda proporcionar la fuerte garantía de excepción. Significativamente, solo puede proporcionar la garantía de excepción fuerte en el caso trivial donde no hace nada.

Herb Sutter habla de un caso similar (y más intuitivo) en el que una función toma un argumento por valor que tiene un constructor de copia de lanzamiento. Puede etiquetar dicha función sin excepción. Técnicamente, la excepción ocurre en el "pegamento" entre el código de llamada y la función llamada, no dentro de la función misma. Ese es el caso aquí también. Dado que la excepción no se produce técnicamente dentro de la actualización, podría (quizás) argumentar que la actualización en sí no genera el error y, por lo tanto, puede ofrecer la garantía de excepción fuerte.

Hablando en términos prácticos, si la actualización hace algo, entonces llamarlo (y no hacer nada más) puede llevar a que el estado del mundo cambie y se lance una excepción, rompiendo la fuerte garantía de excepción.

Nir Friedman
fuente
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
maple_shaft