Segfault при удалении указателя - PullRequest
2 голосов
/ 11 февраля 2012

У меня были ошибки при работе с кодом C ++. Я выделил проблему в строке в программе, которая удаляет указатель. Вот простой пример, который выдает ту же ошибку:

int main()
{
  int* pointer=0;
  int number = 3;

  pointer = &number;
  delete pointer;//This line causes a segmentation fault
  pointer=0;

  return 0;
}

Небольшая модификация создает код, который будет работать как положено:

int main()
{
  int* pointer=new int(3);

  delete pointer;//This line now works
  pointer=0;

  return 0;
}

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

Ответы [ 5 ]

16 голосов
/ 11 февраля 2012

Вы должны когда-либо delete память, которая была выделена с new.Автоматические переменные, объявленные в стеке, не обязательно должны быть delete d.Как правило, всегда сопоставляйте типы выделения и освобождения памяти:

  • Память, выделенная с помощью new, должна быть освобождена с помощью delete.
  • Память, выделенная с new [], должна бытьосвобождается с delete [].
  • Память, выделенная с помощью malloc(), должна быть освобождена с free().

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

3 голосов
/ 11 февраля 2012

Вы не можете использовать delete на том, чего не получили с new.Попытка сделать это приведет к неопределенному поведению.Ваша программа потерпела крах, но могло произойти что угодно .

2 голосов
/ 11 февраля 2012

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

В первой программе указатель указывает на статически выделенную ячейку памяти. Номер переменной является «автоматической» переменной, что означает, что ее память управляется автоматически.

С другой стороны, ввторая программа, указатель, указывает на область памяти, выделенную в сегменте кучи, которую необходимо вручную освободить, вызвав delete.

Вы можете найти эту ссылку полезной.

0 голосов
/ 11 февраля 2012

Когда вы выделяете переменную с новым:

int *a=new int(4);

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

int a=4;

a выделяется в стеке, где есть статическая память.Динамическая память может быть освобождена с удалением от пользователя, но статическая память не может.Статическая память автоматически освобождается, когда вы выходите из функции:

void function()
{
    int a;
}

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

0 голосов
/ 11 февраля 2012

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

...