Вопрос

Не обращая внимания на стиль и дизайн программирования, «безопасно» ли вызывать удаление переменной, выделенной в стеке?

Например:

   int nAmount;
   delete &nAmount;

или

class sample
{
public:
    sample();
    ~sample() { delete &nAmount;}
    int nAmount;
}
Это было полезно?

Решение

Нет, звонить небезопасно delete в переменной, выделенной в стеке.Вам следует позвонить только delete о вещах, созданных new.

  • Для каждого malloc или calloc, там должен быть ровно один free.
  • Для каждого new там должен быть ровно один delete.
  • Для каждого new[] там должен быть ровно один delete[].
  • Для каждого выделения стека не должно быть явного освобождения или удаления.Деструктор вызывается автоматически, если это применимо.

В общем, вы не можете смешивать и сочетать что-либо из этого, например.нет free-инг или delete[]-ing a new объект.Это приводит к неопределенному поведению.

Другие советы

Что ж, давайте попробуем:

jeremy@jeremy-desktop:~$ echo 'main() { int a; delete &a; }' > test.cpp
jeremy@jeremy-desktop:~$ g++ -o test test.cpp
jeremy@jeremy-desktop:~$ ./test
Segmentation fault

Так что, видимо, это совсем не безопасно.

Имейте в виду, что когда вы выделяете блок памяти с помощью new (или malloc, если на то пошло), фактически выделенный блок памяти будет больше, чем вы запросили.Блок памяти также будет содержать некоторую бухгалтерскую информацию, поэтому, когда вы освободите блок, его можно будет легко вернуть в свободный пул и, возможно, объединить с соседними свободными блоками.

Когда вы попытаетесь освободить любую память, которую вы не получили из новой, этой бухгалтерской информации там не будет, но система будет вести себя так, как есть, и результаты будут непредсказуемыми (обычно плохими).

Да, это неопределенное поведение:переходя к delete все, что не пришло из new это УБ:

Стандарт C++, раздел 3.7.3.2.3:Значение первого аргумента, передаваемого одной из функций освобождения, предусмотренных в стандартной библиотеке, может быть null значение указателя;если да, и если функция освобождения предоставляется в стандартной библиотеке, вызов функции освобождения не имеет никакого эффекта.В противном случае значение, передаваемое в operator delete(void*) в стандартной библиотеке должно быть одно из значений, возвращаемых предыдущим вызовом любого из operator new(std::size_t) или operator new(std::size_t, const std::nothrow_t&) в стандартной библиотеке.

Последствия неопределенного поведения, ну, неопределенны.«Ничего не происходит» — такое же значимое следствие, как и все остальное.Однако обычно «сразу ничего не происходит»:освобождение недопустимого блока памяти может иметь серьезные последствия при последующих вызовах распределителя.

Немного поигравшись с g++ 4.4 в Windows, я получил очень интересные результаты:

  1. вызов удаления переменной стека, похоже, ничего не делает.Ошибок не возникает, но после удаления я могу без проблем получить доступ к переменной.

  2. Имея класс с методом с delete this успешно удаляет объект, если он выделен в куче, но не если он выделен в стеке (если он есть в стеке, ничего не происходит).

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

Нет, память, выделенная с использованием нового, должна быть удалена с использованием оператора Delete, и что выделено с использованием Malloc должна быть удалена с помощью бесплатного.И нет необходимости освобождать переменную, выделенную в стеке.

Ангел теряет крылья...Вы можете только позвонить delete по указателю, выделенному с помощью new, в противном случае вы получите неопределенное поведение.

здесь память выделяется с помощью стека, поэтому нет необходимости удалять ее внешне, но если вы выделили динамически

как int *a = new int ()

тогда вам нужно удалить a, а не удалять &a (a само по себе является указателем), потому что память выделяется из свободного хранилища.

Вы уже сами ответили на вопрос. delete должен использоваться только для указателей, полученных через new.Делать что-либо еще — это простое неопределенное поведение.

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

Это UB, потому что вы не должны вызывать delete для элемента, который не был динамически выделен с помощью new.Это так просто.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top