Почему в освобожденной структуре в C все еще есть данные? - PullRequest
3 голосов
/ 02 июня 2010

Когда я запускаю этот код:

#include <stdio.h>

typedef struct _Food
{
    char          name [128];
} Food;

int
main (int argc, char **argv)
{
    Food  *food;

food = (Food*) malloc (sizeof (Food));
snprintf (food->name, 128, "%s", "Corn");

free (food);

printf ("%d\n", sizeof *food);
printf ("%s\n", food->name);
}

Я все еще получаю

128
Corn

хотя я освободил еду. Почему это? Действительно ли память свободна?

Ответы [ 7 ]

10 голосов
/ 02 июня 2010

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

По сути, это потому, что этотакой маленький пример, что это работает.Если бы между вызовами free и print были какие-либо другие вызовы malloc, есть вероятность, что вы этого не увидите, и, скорее всего, произойдет аварийный сбой.Вы не должны полагаться на это поведение.

2 голосов
/ 02 июня 2010

sizeof - операция во время компиляции, поэтому распределение памяти не изменится, как она работает.

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

Посмотрите, есть ли в вашей среде разработки параметр отладки выделения памяти - в некоторых есть настройки для перезаписи блоков чем-то вроде 0xDEADBEEF при free.

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

2 голосов
/ 02 июня 2010

Нет ничего лучше бесплатной еды :) Когда вы «освобождаете» что-то, это означает, что то же пространство снова готово для использования чем-то другим. Это НЕ означает заполнение мусором. Во-вторых, значение указателя не изменилось - если вы серьезно программируете, вы должны установить указатель на NULL, как только вы освободите его, чтобы потенциальные нежелательные обращения, подобные этому, не происходили.

2 голосов
/ 02 июня 2010

Освобождение памяти не обязательно перезаписывает ее содержимое.

1 голос
/ 02 июня 2010

В C. нет такой вещи, как "struct has data" или "struct not data". В вашей программе есть указатель, который указывает где-то в памяти. Пока эта память принадлежит вашему приложению (то есть не возвращается в систему), она всегда будет содержать что-то. Это «что-то» может быть полным мусором или выглядеть более или менее значимым. Кроме того, память может содержать мусор, который выглядит как нечто значимое (остатки ранее сохраненных данных).

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

Что касается языка Си, то, что вы делаете, представляет собой неопределенное поведение. Вы не можете проверить, имеет ли освобожденная структура «данные» или нет. Вопрос «почему», который вы задаете, на самом деле не существует в области языка C.

1 голос
/ 02 июня 2010

free сообщает распределителю памяти, что он может повторно использовать этот блок памяти, ничего больше. К счастью, блок не перезаписывается нулями или чем-то еще, потому что это может быть довольно дорогой операцией! Что делает , так это делает любую дальнейшую разыменовку указателя неопределенной, но «неопределенное» поведение вполне может означать «делать то же самое, что и раньше» - вы просто не можете на это полагаться. В другом компиляторе, другом runime или при других условиях он может вызвать исключение, или завершить программу, или повредить другие данные, так что ... просто НЕ.

0 голосов
/ 02 июня 2010

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

В системах win32 (по крайней мере до XP) это именно , а не . Microsoft создала свою подсистему памяти в 32-битных Windows, специально сохраняя блоки памяти для обеспечения совместимости с хорошо известными приложениями MS-DOS, которые использовали память после ее освобождения.

В модели программирования MS-DOS отсутствует концепция отображения или пространства процесса, поэтому ошибки такого типа не отображались как программные сбои, пока они не были выполнены как программы в режиме DOS под Windows95.

Такое поведение сохранялось для 32-битной Windows более десяти лет. Это может измениться теперь, когда устаревшая совместимость отменяется в таких системах, как Vista и 7.

...