Почему освобожденная структура в C все еще имеет данные?

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

#include  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 

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

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

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

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

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

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

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

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

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

    free сообщает распределителю памяти, что он может повторно использовать этот блок памяти, ничего больше. Это не перезаписывает блок нулями или чем-то – к счастью, потому что это может быть довольно дорогостоящая операция! То, что он делает , это сделать любое разыменование указателя неопределенным, но поведение «неопределенного» может очень хорошо означать «делать то же, что и раньше» – вы просто не можете полагаться на него. В другом компиляторе, другом времени выполнения или при других условиях он может генерировать исключение или прекращать работу программы или искажать другие данные, поэтому … просто НЕ ДЕЛАЙТЕ.

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

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

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

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

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

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

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

    Давайте будем гением компьютера.