2009-12-21 6 views
2

난 작은 C 프로그램을 실행했다 : 메모리 손상

#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); '는 no-op이다. 또한 OP의 예제에서'malloc'은'NULL'을 반환 할 수있었습니다. –

0

이 기능을 구현 한 OS (Linux, Windows ...)의 구현에 따라 다릅니다. 그들의 동작은 OS (정의되지 않은 동작)에 따라 다를 수 있으므로 의존하지 않아야하며 프로그램에서 할당 된 모든 메모리를 한 번만 비워야합니다.

EDIT : OS에 따라 다르지만 OS에 따라 다른 표준 라이브러리의 일부입니다.

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() 포인터를 성공적으로 가져 오면 free()을 호출하면 정의되지 않은 동작이 발생합니다. 프로그램에서 불행하게도 을 비롯한 모든 작업을 수행 할 수 있습니다.. 나는 "불행하게도"라고 말합니다. 왜냐하면 그것은 보안에 대한 느낌을주기 때문에 free() 포인터가 두 번 이상 유효합니다.

+0

+1, 멋지게 설명했습니다. –

+0

free()는 double free에 대해 결코 불평하지 않고, 항상 첫 번째 free 블록을 할당하는 malloc()과 결합하여 재앙을위한 완벽한 처방입니다. – jbcreix

+0

@jbcreix : 구현의 품질 문제입니다. 일부 시스템에서는 이중 해제 등에 대한 추가 검사가 필요하지 않을 수 있습니다. 다른 시스템/용도에서는 이러한 검사에 대해 완벽한 의미를 갖습니다. –

0

힙 손상으로 인해 문제가 즉시 발생할 필요가 없습니다. 해제 된 메모리 (또는 메모리의 일부)가 다른 구조를 할당하는 데 사용되면 문제가 발생할 수 있습니다. free 메모리를 두 번 이상 지정하는 것은 항상 UB (정의되지 않음)이므로 그 순간 악의 영향을 볼 수 없더라도 수행하지 않아야합니다.

+0

원래 포스터가 다시 포인터를 사용하려고하지 않기 때문에이 질문은 힙 손상이 아니라고 생각합니다. 대신, 그들은 동일한 포인터에서 여러 번 무료 호출에 대해 문의합니다. – Anton

+0

여러 개의 free를 호출하면 힙이 손상 될 수 있습니다. 그것은 여전히 ​​OP의 질문에 대답, 나는 믿습니다. 또한 같은 포인터 일 필요는 없으며 재사용 할 수있는 동일한 메모리이기 때문에 손상 될 수 있습니다. –

+0

같은 번호로 여러 번 무료로 호출하면 힙이 손상 될 수 있습니다. – caf

0

대부분의 컴파일러의 DEBUG 빌드가이 유형의 실패를 감지하고 정확히 어떤 일이 일어 났는지보고 할 것으로 기대합니다. 그래서 MSVC 않습니다.

RELEASE에서는 예측할 수없는 동작을보다 빨리 생성하도록 최적화 할 수 있습니다.

1

그냥 다른 답변을 추가하려면 포인터를 NULL로 설정 한 다음 free()를 호출하면 동작이 더 이상 정의되지 않는다는 점에 유의하고 싶습니다. 꽤 많은 노약자입니다. 그러나 포인터가 해제되고 다른 위치 (심지어 NULL)에 포인터를 할당하기 전에 다시 free()를 호출하면 어떤 일이 발생하는지 확신 할 수 없습니다. 일부 구현에서는 코어 덤프가 발생할 수 있으며 다른 일부에서는 아무 것도 발생하지 않습니다.