#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
ornew(std::nothrow)
, и для этогоdelete[]
требуется указатель, возвращаемыйnew[]
ornew(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[]
.