C ++ удалить после нового с конкретными запрошенными байтами - PullRequest
0 голосов
/ 26 октября 2019

Свободен ли этот код памяти памяти?

char *buffer = (char *) (::operator new(n));
delete buffer;

Отличается ли он от варианта «традиционной скобочной формы» (когда мы говорим о примитивных типах):

char *buffer = new char[n];
delete[] buffer;

Я предполагаю, что есть 3 варианта:

a) будет освобожден только 1 байт (n - 1 утечка)

b) будет освобожден весь выделенный блок (n байтов)

в) неопределенное поведение (реализация зависит)

Мои мысли: для примитивного типа char только free срабатывает (не вызывается деструктор) и free знает, сколько байтов должно быть освобождено (чтохранится в метаинформации распределителя). Итак, этот код должен быть правильным.

Добавлено:

Смешивание operator new/delete и expression new/delete приведет к неопределенному поведению. Так что это плохой код.

Опция использования operator delete также плоха в соответствии с http://eel.is/c++draft/expr.delete#2:

char *buffer = (char *) (::operator new(n));
::operator delete(buffer);

Так что единственный вариант:

char *buffer = new char[n];
delete[] buffer;

Ответы [ 2 ]

2 голосов
/ 26 октября 2019

Согласно http://eel.is/c++draft/expr.delete#2

В выражении удаления из одного объекта значение операнда удаления может быть

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

Если нет, поведение не определено.

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

Кроме того, "undefined«поведение» не означает, что это зависит от реализации, как вы предлагаете (вещи, зависящие от реализации, обозначены в стандарте как «определенные реализацией»)Неопределенное поведение означает именно то, что оно означает, компилятору разрешено делать все, что ему нравится. Проверьте этот вопрос: Неопределенное, неопределенное и определяемое реализацией поведение

1 голос
/ 26 октября 2019
char* buffer = static_cast<char*>(::operator new(n));
::operator delete(buffer);

может использоваться для ручного / пользовательского управления памятью:

class Demo
{
    // some pretty complex class...
};

Demo* buffer = static_cast<Demo*>(::operator new(sizeof(Demo)));

new (buffer) Demo();
// placement new requires explicit destructor calls!
// (only occassion you ever need to do so)
buffer->~Demo();

::operator delete(buffer);

или аналогично варианту массива. Если у вас есть особые требования к выравниванию, которые не охватываются выравниванием по умолчанию, то есть перегрузки, принимающие спецификацию выравнивания в качестве второго параметра.

Обычно такие вещи вам никогда не понадобятся, но это может быть полезно для критичных к производительностикод (чтобы избежать последующего выделения и освобождения), если у вас ограниченные ресурсы памяти (например, на микроконтроллерах) или если вы находитесь в критической среде безопасности (где вам может быть разрешено выделять только при запуске, но не позднее, чтобы предотвратитьсбои из-за std::bad_alloc).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...