Несоответствующее удаление больше не является неопределенным поведением?

#c #language-lawyer #dynamic-memory-allocation #delete-operator #c 17

#c #язык-юрист #динамическое выделение памяти #оператор удаления #c 17

Вопрос:

Я заметил, что проект C от e51a2152 больше не содержит следующую формулировку:

поведение не определено, если значение, предоставленное operator delete(void*) в стандартной библиотеке, не является одним из значений, возвращенных предыдущим вызовом или operator new(std::size_t) или operator new(std::size_t, const std::nothrow_tamp;) в стандартной библиотеке, и поведение не определено, если значение, предоставленное operator delete[](void*) в стандартной библиотеке, не является одним из значений, возвращенных предыдущим вызовом или operator new[](std::size_t) илив operator new[](std::size_t, const std::nothrow_tamp;) стандартной библиотеке.

Означает ли это, что код, подобный

 int * const p = new int[42];
delete p; // instead of delete[] p;
  

больше не будет иметь неопределенного поведения или я что-то упускаю?

Комментарии:

1. Вы неправильно читаете. В нем говорится, что для этого delete требуется указатель, возвращаемый new or new(std::nothrow) , и для этого delete[] требуется указатель, возвращаемый new[] or new(std::nothrow)[] . Как и всегда.

2. Это черновик по уважительной причине. Каждый поставщик компилятора знает, что это неопределенное поведение, и будет рассматривать его как таковое. В стандарте будет указано то, что, по мнению этих поставщиков, должно быть сказано.

Ответ №1:

В любом случае этот абзац касается функций выделения / освобождения. Несоответствующие new / delete выражения обрабатываются в [expr.delete]/2, который остается неизменным:

В первой альтернативе (удалить объект) значением операнда delete может быть значение указателя null, указатель на объект, не являющийся массивом, созданный предыдущим новым выражением, или указатель на подобъект ([intro.object] ), представляющий базовый класс такого объекта(Предложение [class.derived]). Если нет, поведение не определено. Во второй альтернативе (удалить массив) значением операнда delete может быть значение нулевого указателя или значение указателя, полученное в результате предыдущего нового выражения массива.82 Если нет, поведение не определено.

Ответ №2:

Формулировка просто была перенесена в описание для operator delete :

[new.delete.single]/12: Требуется: ptr должен быть нулевым указателем или его значение должно представлять адрес блока памяти, выделенного предыдущим вызовом a (возможно, замененного) operator new(std::size_t) или operator new(std::size_t, std::align_val_t) который не был признан недействительным промежуточным вызовом operator delete .

Смотрите Здесь изменения в репозитории GitHub. Существует аналогичная формулировка для версии массива. Семантически ничего не изменилось, это просто то, как это выражено в стандарте.

Комментарии:

1. Обратите внимание, что стандарт указывает, что реализация operator new[] вызовов по умолчанию operator new и возвращает результат. Итак, если — и это большое, если — ничто не заменяет реализацию форм массива по умолчанию, я думаю, что формулировку можно прочитать, чтобы разрешить вызов operator delete чего-либо, возвращаемого operator new[] .