delete [] с неопределенным поведением другого типа? - программирование

delete [] с неопределенным поведением другого типа?

Мне интересно, если это неопределенное поведение:

#include <stdint.h>

int main() {
  auto* p = new uint8_t[32];
  float* c = reinterpret_cast<float*>(p);
  delete[] c;
}

В стандарте есть

Если нет, поведение не определено. Во втором альтернативе (удалить массив) значение операнда удаления может быть значением нулевого указателя или значением указателя, которое было получено из предыдущего массива new-expression.79 Если нет, поведение не определено. [Примечание: это означает, что синтаксис выражения-удаления должен соответствовать типу объекта, выделенного новым, а не синтаксис нового выражения. - конечная нота]

Поэтому интерпретация несколько неясной фразы

это означает, что синтаксис выражения-delete должен соответствовать типу объекта, выделенного новым, а не синтаксис нового выражения

Могу сказать, что вышеизложенное - это неопределенное поведение, правильно?

4b9b3361

Ответ 1

Да, поведение не определено.

Указатель, переданный для delete[] должен быть того же типа, что и тот, который вы возвращаете из new[].

Обратите внимание, что для delete и new указатель, отправленный для delete может быть связан полиморфизмом.

Ответ 2

Да, код действительно не определено. Выражение означает, что он все равно будет UB, когда вы перепишете его как

int main() {
  void* p;
  {
     using T = uint8_t;
     p = new T [32];
  }
  {
    using T = float;
    T* c = reinterpret_cast<float*>(p);
    delete[] c; // The behaviour is still undefined.
  }
}

IOW, типы действительно должны соответствовать точно, а не только по имени.

Ответ 3

Неопределенное поведение вызывает delete[] p; если p имеет другой тип, возвращаемый new[].

В частности:

struct Base { virtual ~Base() = default; };
struct Derived: Base { int a; };

int main() {
    Base* p = new Derived[5];
    delete[] p;
}

Является также неопределенным поведением.


@Justin предоставил соответствующую стандартную цитату в комментарии, см. Здесь:

5.3.5 [expr.delete]

(3) В первом альтернативе (объект удаления), если статический тип подлежащего удалению объекта отличается от его динамического типа, статический тип должен быть базовым классом динамического типа подлежащего удалению объекта, а статический тип должен иметь виртуальный деструктор или поведение не определено. Во втором альтернативе (удалить массив), если динамический тип подлежащего удалению объекта отличается от его статического типа, поведение не определено.

Обратите внимание на то, что не существует положения для полиморфных отношений в случае массива удаления, которое я подчеркнул; вопреки случаю объекта удаления.