Подтвердить что ты не робот

Освобождение памяти дважды

В C и С++ освобождение указателя NULL не приведет к тому, что ничего не сделано.

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

Это правда? Что происходит под капотом, когда вы освобождаете память дважды?

4b9b3361

Ответ 1

int *p = malloc(sizeof(int));
//value of p is now lets say 0x12345678

*p = 2;
free(p); //memory pointer is freed, but still value of p is 0x12345678
         //now, if you free again, you get a crash or undefined behavior.

Итак, после free в первый раз вы должны сделать p = NULL, поэтому, если (случайно), free(p) вызывается снова, ничего не произойдет.

Вот почему освобождение памяти в два раза меньше undefined: Почему бесплатные сбои при вызове дважды

Ответ 2

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

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

Освобождение снова - это не то же самое, что сказать free(NULL), и приведет к поведению undefined.

Ответ 3

Это поведение undefined, которое может привести к повреждению кучи или другим серьезным последствиям.

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

Вот что обычно происходит. Реализация кучи получает адрес и пытается "взять на себя ответственность" блока по этому адресу, изменив свои собственные служебные данные. В зависимости от реализации кучи все может случиться. Возможно, это работает, и ничего не происходит, возможно, данные службы повреждены, и у вас есть повреждение кучи.

Так что не делай этого. Это поведение undefined. Что бы ни случилось, может случиться.

Ответ 4

Да, "undefined поведение", которое почти всегда приводит к сбою. (в то время как "undefined поведение" по определению означает "что угодно", различные типы ошибок часто ведут себя вполне предсказуемым образом. В случае free() поведение неизменно является segfault или соответствующей "ошибкой защиты памяти", характерной для ОС. )

То же самое, если вы освободите() указатель на что-либо еще, кроме NULL или что-то, что вы malloc'd.

char x; char* p=&x; free(p);//сбой.

Ответ 5

Чтобы избежать бесплатного дважды, я всегда использую MACRO для свободной памяти:

#ifdef FREEIF
# undef FREEIF
#endif
#define FREEIF( _p )  \
if( _p )              \
{                     \
        free( _p );   \
        _p = NULL;    \
}

этот макрос устанавливает p = NULL, чтобы избежать оборванного указателя.

Ответ 6

Когда вы вызываете бесплатный указатель, ваш указатель не будет установлен в NULL. Свободное пространство возвращается только в пул, который будет доступен для распределения снова. Вот пример тестирования:

#include <stdio.h>
#include <stdlib.h>

int main(){
    int* ptr = (int*)malloc(sizeof(int));
    printf("Address before free: %p\n", ptr);
    free(ptr);
    printf("Address after free: %p\n", ptr);
    return 0;
}

Эта программа выводит для меня:

Address before free: 0x950a008
Address after free: 0x950a008

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

Ответ 7

free() освобождает пространство памяти к ptr, который, должно быть, был возвращенный предыдущим вызовом malloc(), calloc() или realloc(). В противном случае, или если free (ptr) уже вызывается раньше, undefinedпроисходит поведение. Если        ptr имеет значение NULL, операция не выполняется.

Итак, вы получаете поведение undefined, и все может случиться.

Ответ 8

1) Обработка динамической памяти не выполняется компилятором. Есть библиотеки времени выполнения, которые позаботятся об этом. Напр.: glibc предоставляет API, такие как malloc и free, которые внутренне выполняют системные вызовы (sys_brk) для обработки области кучи.

2) Освобождение одной и той же памяти в два раза относится к следующим условиям: Предположим, что у вас есть char * cptr;

Вы выделяете память, используя: cptr = (char *) malloc (SIZE);

Теперь, когда вам больше не нужна эта память, вы можете освободить ее, используя следующую команду: свободные (СРКИ);

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

Предположим, что в более поздний момент в программе вы снова вызываете бесплатный (cptr), то это не является допустимым условием. Этот сценарий, в котором вы освобождаете одну и ту же память дважды, известен как проблема "освобождение памяти дважды".

Ответ 9

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

#include <stdio.h>      /* printf, scanf, NULL */
#include <stdlib.h>     /* malloc, free, rand */

int main ()


  {
  int i,n;
  char * buffer;

  printf ("How long do you want the string? ");
  scanf ("%d", &i);

  buffer = (char*) malloc (i+1);
  if (buffer==NULL) exit (1);

  for (n=0; n<i; n++)
          buffer[n]=rand()%26+'a';
  buffer[i]='\0';

  printf ("Random string: %s\n",buffer);
  free (buffer);
  free (buffer);

  return 0;
}

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

 /* wrapper for free */
    void *cs_free (void *p)
    {
        if (p) free (p) ;       /* free p if it is not already NULL */
        return (NULL) ;         /* return NULL to simplify the use of    

    }

Эта функция может обрабатывать проблемы с памятью. Обратите внимание, что вам необходимо позаботиться о том, что malloc возвращает NULL в некоторых случаях