о malloc () и free () в C - PullRequest
       26

о malloc () и free () в C

3 голосов
/ 20 сентября 2010

У меня есть следующий C-код:

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

typedef struct node
{
    int a;
}node;

int main()
{
    node * n;

    printf("\n%d\n",n->a);

    n  = (node *) malloc ( sizeof( node ));

    printf("\n%d\n",n->a);
    n->a = 6;
    printf("\n%d\n",n->a);
    free(n);
    printf("\n%d\n",n->a);
    n->a = 4;
    printf("\n%d\n",n->a);
    return 0;
}

Получено:

1314172

0

6

0

4

Мой вопрос даже после free (n), почему n-> a = 0 и как мы можем также переназначить его на любое значение, например n-> a = 4?

Не освобождает ли блок памяти, на который указывает n, недействительный ??

Ответы [ 7 ]

15 голосов
/ 20 сентября 2010
free(n);
n->a = 4; // is not guaranteed to work, might crash on some implementations

Вызывает неопределенное поведение.

, почему n-> a = 0 и как мы можем также переназначить его на любое значение, например n-> a = 4?

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

PS: Не пишите такой код.

РЕДАКТИРОВАТЬ :

As Jonathan заметил, что ваш код вызывает Undefined Behavior задолго до вас free(), а затем разыменовывается n.

node * n; //n is not initialized
printf("\n%d\n",n->a);  //dereferencing a wild pointer invokes UB.
13 голосов
/ 20 сентября 2010

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

4 голосов
/ 20 сентября 2010

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

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

Если вы запускаете этот код в ряде различных сред, вы обнаружите, что в некоторыхв окружениях он всегда работает, в некоторых он всегда вызывает ошибку, но во многих других он работает «большую часть времени».Это делает C довольно сложным для отладки!:)

4 голосов
/ 20 сентября 2010

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

Вам решать, чтобы вы не ссылались на бесплатные 'д память.

1 голос
/ 20 сентября 2010

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

Как вы найдете в будущем; Вы будете в конечном итоге делать это случайно; и обычно плохие вещи (тм) произойдет

0 голосов
/ 21 сентября 2010

Большинство ОС будет выделять определенное минимальное пространство, которое будет равно или больше, чем запрошенное вами пространство. После того, как вы позвоните бесплатно, это пространство не вернется к ОС, а останется с вами для дальнейшего использования. Следовательно, вы можете сойти с рук что-то вроде того, что вы написали выше.

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

0 голосов
/ 20 сентября 2010

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

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

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

ТамЕсть несколько способов получить это, например, с помощью mmap(), но это не совсем правильная причина для использования этой функции.

...