Czy trywialne destruktory powodują aliasing

C ++ 11 §3.8.1 deklaruje, że dla obiektu z trywialnym destruktorem mogę zakończyć jego żywotność, przypisując do jego pamięci. Zastanawiam się, czy trywialne destruktory mogą przedłużyć żywotność obiektu i spowodować aliasing nieszczęść przez „zniszczenie obiektu”, który zakończył żywot znacznie wcześniej.

Na początek coś, co wiem, jest bezpieczne i wolne od aliasów

void* mem = malloc(sizeof(int));
int*  asInt = (int*)mem;
*asInt = 1; // the object '1' is now alive, trivial constructor + assignment
short*  asShort = (short*)mem;
*asShort = 2; // the object '1' ends its life, because I reassigned to its storage
              // the object '2' is now alive, trivial constructor + assignment
free(mem);    // the object '2' ends its life because its storage was released

Teraz coś, co nie jest tak jasne:

{
    int asInt = 3; // the object '3' is now alive, trivial constructor + assignment
    short* asShort = (short*)&asInt; // just creating a pointer
    *asShort = 4; // the object '3' ends its life, because I reassigned to its storage
                  // the object '4' is now alive, trivial constructor + assignment
    // implicitly, asInt->~int() gets called here, as a trivial destructor
}   // 'the object '4' ends its life, because its storage was released

§6.7.2 stwierdza, że ​​obiekty automatycznego przechowywania są niszczone na końcu zakresu, wskazując, że destruktor zostanie wywołany.Jeśli istnieje int do zniszczenia,*asShort = 2 jest naruszeniem aliasingu, ponieważ dereferencjonuję wskaźnik niepowiązanego typu. Ale jeśli długość życia liczby całkowitej skończyła się wcześniej*asShort = 2, a następnie wywołuję int destruktor w krótkim czasie.

Widzę kilka konkurencyjnych sekcji dotyczących tego:

§ 3.8.8 czyta

Jeśli program kończy czas życia obiektu typu T ze statycznym (3.7.1), wątkiem (3.7.2) lub automatycznym (3.7.3) czasem przechowywania i jeśli T ma nietrywialny destruktor, 39 program musi upewnij się, że obiekt typu oryginalnego zajmuje to samo miejsce przechowywania, gdy ma miejsce niejawne wywołanie destruktora; w przeciwnym razie zachowanie programu jest niezdefiniowane.

Fakt, że wywołują typy T z nietrywialnym destruktorem, ponieważ dają niezdefiniowane zachowanie, wydaje mi się wskazywać, że posiadanie innego typu w tej lokalizacji pamięci z trywialnym destruktoremjest zdefiniowałem, ale nie mogłem znaleźć nigdzie w specyfikacji, która to zdefiniowała.

Taka definicja byłaby łatwa, gdyby zdefiniowano trywialny destruktor jako noop, ale w specyfikacji tej jest bardzo mało.

§6.7.3 wskazuje, że goto mogą przeskakiwać do zakresów, których zmienne mają trywialne konstruktory i trywialne destruktory. Wydaje się to sugerować wzorzec, w którym trywialne destruktory mogą być pomijane, ale wcześniejsza część specyfikacji dotycząca niszczenia obiektów na końcu zakresu nie wspomina o tym.

Wreszcie jest sassy czytanie:

§ 3.8.1 wskazuje, że wolno mi rozpocząć żywotność obiektu w dowolnym momencie, jeśli jego konstruktor jest trywialny. To wydaje się wskazywać, że mógłbym zrobić coś takiego

{
    int asInt = 3;
    short* asShort = (short*)&asInt;
    *asShort = 4; // the object '4' is now alive, trivial constructor + assignment
    // I declare that an object in the storage of &asInt of type int is
    // created with an undefined value.  Doing so reuses the space of
    // the object '4', ending its life.

    // implicitly, asInt->~int() gets called here, as a trivial destructor
}

Jedynym z tych odczytów, który wydaje się sugerować, że jakiekolwiek problemy z aliasingiem, jest sam §6.7.2. Wydaje się, że odczytany jako część całej specyfikacji trywialny destruktor nie powinien w żaden sposób wpływać na program (choć z różnych powodów). Czy ktoś wie, co dzieje się w tej sytuacji?

questionAnswers(2)

yourAnswerToTheQuestion