2009-12-21 5 views
2

я управлял небольшой гр программы:памяти коррупции

#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

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

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

+1

Хороший способ предотвратить это: 'free (ptr); ptr = NULL; ', поскольку' free (NULL); 'is no-op. Кроме того, в примере OP 'malloc' мог возвращать' NULL'. – 2012-01-14 14:48:01

0

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

EDIT: он не является частью операционной системы, но из стандартной библиотеки, которые различаются в зависимости от операционной системы.

1

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

7

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

  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() 'd указатель успешно, вызывая free(), это неопределенное поведение: программа может делать что угодно, в том числе (к сожалению), , похоже, ничего плохого не делает. Я говорю «к сожалению», потому что это может дать вам ощущение безопасности, что все в порядке free() указатель более одного раза.

+0

+1, приятно объяснил. –

+0

Свободный(), который никогда не жалуется на двойное освобождение в сочетании с malloc(), который всегда выделяет первый свободный блок, является идеальным рецептом для катастрофы. – jbcreix

+0

@jbcreix: Это проблема качества реализации. В некоторых системах, возможно, не нужны дополнительные проверки для двойных разрядов и т. Д. В других системах/целях это имеет смысл для таких проверок. –

0

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

+0

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

+0

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

+0

Вызов нескольких раз на одном и том же * может * вызвать повреждение кучи. – caf

0

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

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

1

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

 Смежные вопросы

  • Нет связанных вопросов^_^