Сложность понимания поведения свободных ()

int main()
{
int *ptr, **ptr1;
ptr = (int*)malloc(sizeof(int));
ptr1 = (int**)malloc(sizeof(int));
free(ptr);
*ptr = 12345;
ptr1 = &ptr;

//free(ptr);
//**ptr1 = 23456;
printf("%d \n", **ptr1);
system("pause");
return 0;
}

Как *ptr сохранить значение 12345когда память уже была freed? А сейчас ptr должен указывать на garbage,
Почему это происходит?

3

Решение

Этот код очень ошибочен на многих уровнях.

  1. Не бросайте возвращаемое значение от malloc() в С.
  2. Вы выделяете неправильные размеры; ptr1 потребности sizeof *ptr1не sizeof (int), Это указатель!
  3. Помни что malloc() может потерпеть неудачу. Проверьте возвращаемое значение перед использованием.
  4. Не (просто не) доступ к памяти после того, как вы free()д это. Неопределенное поведение.

Также обратите внимание, что сам указатель не разрушается при звонке free() в теме; вещь, которая уходит, — это память, на которую ссылается указатель. Таким образом, вы можете хранить биты указателя в самом указателе, если хотите. Однако в редких случаях это необходимо, и следует проявлять осторожность, когда / если вы проверяете биты.

8

Другие решения

Указатель освобождается, но он все еще указывает, куда бы он ни делался, когда был выделен. Для этого считается серьезной ошибкой программирования. Но среда выполнения (обычно) не помогает выявлять или исправлять такие ошибки.

Не направляйте пистолет на себя и не нажимайте на курок!

4

Это неопределенное поведение, все может случиться.

free(ptr);
*ptr = 12345;

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

3

Вы, кажется, не понимаете неопределенного поведения. В основном, поведение не определено. Это может сделать что угодно, включая (но не ограничиваясь) следующее:

  1. авария
  2. Делай то, что ты ошибочно ожидал
  3. Делайте то, что вы сказали, но без ошибок
  4. Запустите игру тетрис на вашей консоли
  5. переформатировать ваш жесткий диск

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

Попытка определить неопределенное поведение ставит вас в тупик. Гораздо лучше просто не делать это в первую очередь.

1

free () освобождает память, указанную * ptr, но не изменяет значение * ptr, поэтому, если это значение не конфликтует ни с чем другим, оно все равно будет работать, но память может быть выделена другим процессом случайным образом. Обычная практика — делать бесплатно (ptr); ptr = NULL, чтобы избежать случайного повторного использования памяти без другого вызова malloc.

0
По вопросам рекламы [email protected]