son reglas regla razonamiento qué principios principio jurídico juridica entre ejemplos dworkin distinción diferencia criterios argumentacion c++ language-lawyer undefined-behavior

c++ - razonamiento - ¿Diferencia en las reglas de fin de vida?



reglas y principios dworkin (2)

https://en.cppreference.com/w/cpp/language/lifetime en la sección de Notas tiene este código, reproducido aquí:

struct A { int* p; ~A() { std::cout << *p; } // if n outlives a, prints 123 }; void f() { A a; int n = 123; // if n does not outlive a, this is optimized out (dead store) a.p = &n; }

¿Qué es lo que está tratando de decir en esta sección de Notas ?

Por lo que entiendo, el código es UB (o lo es) ya que está claro que n no sobrevive a .

¿Qué significa por:

diferencia en las reglas de fin de vida útil entre los objetos que no son de clase (fin de la duración de almacenamiento) y los objetos de clase (orden inverso de construcción)

Pero no dice cómo importa.

Estoy muy confundido por toda esta sección.


Este ejemplo está tomado de Core Language Issue 2256 :

Sección: 6.8 [basic.life] Estado: elaboración Redactor : Richard Smith Fecha: 2016-03-30

De acuerdo con 6.4 [basic.lookup] bullet 1.4, el siguiente ejemplo ha definido el comportamiento porque la vida útil de n extiende hasta que se libera su almacenamiento, que es después de que se ejecute el destructor de:

void f() { struct A { int *p; ~A() { *p = 0; } } a; int n; a.p = &n; }

Sería más coherente si el final de la vida útil de todos los objetos, independientemente de si tienen un destructor no trivial, se tratara de la misma manera.

Notas de la reunión de marzo de 2018:

CWG estuvo de acuerdo con la dirección sugerida.

La idea clave es si la vida útil de un objeto termina con su destrucción o en el momento en que se libera su memoria puede afectar la semántica de un programa. En el ejemplo

  1. si la vida útil de n termina en la destrucción de n , el programa no está definido;

  2. Si la vida útil de n finaliza hasta que se libera la memoria, el programa tiene el comportamiento definido 1 .

Por lo tanto, se requiere una discusión adicional para determinar cuándo finaliza la vida útil de un objeto.

1 Esto se debe a que Core Language Issue 2115 :

Sección: 9.6 [stmt.jump] Estado: redacción Remitente: Richard Smith Fecha: 2015-04-16

El orden relativo entre la destrucción de las variables automáticas al salir de un bloque y la liberación del almacenamiento de las variables no está especificado por la Norma: ¿todos los destructores se ejecutan primero y luego el almacenamiento se liberan, o están intercalados?

Notas de la reunión de febrero de 2016:

CWG acordó que el almacenamiento debería persistir hasta que se completen todas las destrucciones, aunque la regla "como si" permitiría optimizaciones no observables de este pedido.

La intención es que el lanzamiento de memoria de las variables automáticas ocurra después de que se completen todas las destrucciones.


Este es un aspecto extraño de las reglas de vida de C ++. [basic.life] / 1 nos dice que la vida útil de un objeto termina:

  • si T es un tipo de clase con un destructor no trivial ([class.dtor]), se inicia la llamada del destructor, o
  • el almacenamiento que ocupa el objeto se libera o es reutilizado por un objeto que no está anidado dentro de o ([intro.object]).

Énfasis añadido. int no es un "tipo de clase con un destructor no trivial", por lo que su vida útil solo finaliza cuando se libera el almacenamiento que ocupa. Por el contrario, A es un tipo de clase con un destructor no trivial ", por lo que su vida útil termina cuando se llama al destructor.

El almacenamiento para un alcance se libera cuando el alcance se cierra, de conformidad con [basic.stc.auto]/1 :

El almacenamiento para [variables con duración de almacenamiento automático] dura hasta que el bloque en el que se crean sale.

Pero las variables automáticas se destruyen de acuerdo con [stmt.jump]/2 :

Al salir de un alcance (aunque se haya realizado), los objetos con duración de almacenamiento automático que se han construido en ese alcance se destruyen en el orden inverso a su construcción.

Observe que se especifica el orden de destrucción, pero no se especifica el orden de la versión de almacenamiento automático. Esto significa que la implementación podría liberar el almacenamiento justo después de que se destruya cada variable, o liberarlo todo de una vez más tarde, o en algún otro orden arbitrario.

Ahora, el hecho de que use el singular para almacenamiento ("el almacenamiento para ... dura") en lugar de hablar de cada variable individualmente puede sugerir que la intención es que el almacenamiento en su totalidad se publique de una vez para ese alcance. Pero no hay una declaración explícita de esto en la norma. Por lo tanto, siempre que una variable se destruya antes de que se libere su almacenamiento, cualquier orden de destrucción versus liberación parece ser legal.

Esto significa que es totalmente posible que el código funcione, para que n sobreviva a . Pero no se especifica si funciona.