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

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

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

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

но он печатает

 pointer is freed!! 

Я что-то не так?

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

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

В вашей программе много проблем:

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

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

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

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

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

EDIT: это не часть ОС, а стандартная библиотека, которая отличается в зависимости от ОС.

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

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

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