повреждение памяти - PullRequest
       33

повреждение памяти

2 голосов
/ 21 декабря 2009

я запускал небольшую программу c:

#include<stdio.h>
int main()
{
char *p;
p = (char *)malloc(10);
free(p);
free(p);
free(p);
printf("\npointer is freed!!\n");
}

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

но это печать

pointer is freed!!

я где-то ошибаюсь?

Ответы [ 7 ]

7 голосов
/ 21 декабря 2009

Есть несколько проблем с вашей программой:

  1. Поскольку вы используете malloc() и free(), вы должны выполнить #include <stdlib.h> перед вызовом любой из этих функций.
  2. Нет необходимости приводить возвращаемое значение из malloc(): оно возвращает void *, которое можно безопасно назначить любому другому типу указателя (кроме указателей на функции). Итак, вы можете сделать: p = malloc(10);
  3. Когда вы освобождаете указатель, выделенный с помощью malloc() или realloc(), использование значения указателя каким-либо образом является плохим: в частности, вы не можете вызвать free() для него снова.
  4. int main() лучше записать как int main(void).
  5. Поскольку main() возвращает int, вы должны вернуть значение из него. Традиционно 0 означает успех.

Конечно, главная (без каламбура) проблема с вашей программой многократно освобождает ее, но важны и другие проблемы, упомянутые выше. После того, как вы free() успешно указали, вызов free() для него является неопределенным поведением: программа может делать все что угодно, включая (к сожалению), , похоже, ничего плохого не делает . Я говорю «к сожалению», потому что это может дать вам чувство безопасности, что можно free() указатель более одного раза.

7 голосов
/ 21 декабря 2009

Согласно man-странице, «если free (ptr) уже был вызван ранее, происходит неопределенное поведение».

Не нужно взрываться; «ничего не делать» - совершенно приемлемое неопределенное поведение. Также носовые демоны. Не надейся на это.

1 голос
/ 21 декабря 2009

Просто чтобы добавить к другим ответам, я хотел бы отметить, что если вы установите указатель на NULL и затем вызовете free (), поведение больше не будет неопределенным. Это в значительной степени неоперация. Однако, если указатель освобожден и вы снова вызываете free () перед тем, как назначить указатель в другое место (даже NULL), вы не можете быть уверены в том, что произойдет. Это может привести к дампу ядра в некоторых реализациях, а в других ничего не произойдет.

1 голос
/ 21 декабря 2009

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

0 голосов
/ 21 декабря 2009

Я ожидаю, что сборки DEBUG большинства компиляторов смогут обнаруживать ошибки этого типа и точно сообщать, что произошло. Так сделает MSVC.

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

0 голосов
/ 21 декабря 2009

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

0 голосов
/ 21 декабря 2009

Это зависит от реализации вашей ОС (linux, windows ...), которая реализует эту функцию. Их поведение может отличаться в зависимости от ОС (неопределенное поведение), поэтому вы не должны полагаться на них и должны освобождать только один раз всю выделенную память в вашей программе.

РЕДАКТИРОВАТЬ: это не часть ОС, а стандартная библиотека, которые различаются в зависимости от ОС.

...