ptr이 NULL 인 free (ptr)는 메모리를 손상 시킵니까?


112

이론적으로 나는 말할 수 있습니다

free(ptr);
free(ptr); 

이미 해제 된 메모리를 해제하기 때문에 메모리 손상입니다.

하지만 만약

free(ptr);
ptr=NULL;
free(ptr); 

OS가 정의되지 않은 방식으로 동작하기 때문에 무슨 일이 일어나고 있는지에 대한 실제 이론적 분석을 얻을 수 없습니다. 내가 무엇을하든,이 메모리 손상이 아닌가?

NULL 포인터를 해제하는 것이 유효합니까?


1
C 자유 표준에 대해서는 확실하지 않지만 C ++에서는 delete (NULL)가 완벽하게 유효하므로 free (NULL)도 있어야한다고 생각합니다.
Priyank Bolia 2009

14
@Pryank : delete NULLC ++에서는 유효하지 않습니다. delete는 구체적인 유형의 null 포인터 값에 적용될 수 있지만 NULL. delete (int*) NULL합법적이지만 delete NULL.
AnT 2009

따라서 포인터가 NULL free를 가리키면 아무것도 수행하지 않습니다. 메모리를 해제하려면 코딩 할 때마다 free (ptr)를 ptr = NULL?
Vijay

3
아니요. ptr메모리를 가리키고 호출하지 않으면 free메모리가 누수됩니다. 로 설정 NULL하면 메모리에 대한 핸들이 손실되고 누출됩니다. ptr NULL발생하면 호출 free은 작동하지 않습니다.
GManNickG 2009

1
@benjamin : 응? 어떻게 당신이 대체 할 수 있다는 결론을 만들어 free(ptr)함께 ptr = NULL. 아무도 그런 말을하지 않았습니다.
AnT 2009

답변:


224

7.20.3.2 free기능

개요

#include <stdlib.h> 
void free(void *ptr); 

기술

free함수는에서 가리키는 공간을 ptr할당 해제, 즉 추가 할당에 사용할 수 있도록합니다. 경우 ptr널 포인터가 아무런 조치가 발생하지 않습니다.

ISO-IEC 9899를 참조하십시오 .

즉, 야생에서 다른 코드베이스를 살펴보면 사람들이 다음과 같이하는 것을 알 수 있습니다.

if (ptr)
  free(ptr);

이것은 NULL포인터를 해제 할 때 일부 C 런타임 (PalmOS의 경우 였음을 확실히 기억합니다)이 충돌하기 때문 입니다.

하지만 요즘 free(NULL)은 표준의 지시에 따라 nop 라고 가정하는 것이 안전하다고 생각합니다 .


29
아니, PTR = NULL이 방법은 모두 완전히 다른, 무료 (PTR)를 대체하지 않습니다
Prasoon Saurav

7
NO, 그 의미 free(ptr)여기서 ptr널은 부작용이 없다. 그러나 어떤 경우에도, 모든 메모리를 사용하여 할당 malloc()또는 calloc()사용 후 해제해야free()
그레고리 Pakosz을

4
ptr = NULL은 실수로 free (ptr)를 호출하더라도 프로그램이 세그 폴트되지 않도록합니다.
Prasoon Saurav

2
C 표준에서 작동하지 않는다고 말하지만 모든 C 라이브러리가 그렇게 처리한다는 의미는 아닙니다. 무료 (NULL)로 충돌이 발생 했으므로 처음에는 무료 호출을 피하는 것이 가장 좋습니다.
Derick 2013-01-24

6
@WereWolfBoy 그는 피할 의미 free(NULL)에 대한 포인터를 테스트하여 NULL호출하기 전에free()
그레고리 Pakosz

22

모든 표준 호환 버전의 C 라이브러리는 free (NULL)를 no-op으로 처리합니다.

즉, 한때 free (NULL)에서 충돌하는 free 버전이 있었기 때문에 방어적인 프로그래밍 기술이 권장하는 것을 볼 수 있습니다.

if (ptr != NULL)
    free(ptr);

8
-1 [인용 필요]. 오래된 소문 구현 이론 때문에 코드 스타일을 변경하는 것은 나쁜 생각입니다.
Tomas

41
@Tomas-저는 스타일 변경을 권장하지 않았습니다. 일부 스타일에서이 권장 사항이 계속 표시되는 이유를 간단히 설명했습니다.
R Samuel Klatchko 2009

5
@Tomas 3BSD ( winehq.org/pipermail/wine-patches/2006-October/031544.html ) 및 PalmOS 2 개 (둘 다 두 번째 핸드).
Douglas Leeder

7
@Tomas : 문제는 버전 7 Unix와 같은 것입니다. 내가 배웠을 때, free (xyz) where xyz == NULL은 내가 배운 시스템에서 즉각적인 재난을위한 레시피였습니다 (일부 System III 추가 기능이있는 Version 7 Unix를 기반으로하는 PNX를 실행하는 ICL Perq). 하지만 저는 오랫동안 그렇게 코딩하지 않았습니다.
Jonathan Leffler

2
자유 보내고 NULL에 넷웨어 충돌이 너무 ... (그냥 ... 거기에 충돌을 디버깅)
Calmarius

13

ptr이 NULL이면 작업이 수행되지 않습니다.

문서를 말합니다.


자유가 아무것도 수행하지 않는다는 뜻인가요?
Vijay

2
벤자민, 그게 바로 그 의미입니다. 인수가 무효라는 것을 알고 있다면 어떤 성능을 기대할 수 있습니까?
Michael Krelin-해커

12

free(NULL)충돌이 발생한 PalmOS에서 작업 한 것을 기억 합니다.


4
흥미 롭습니다. 이것은 충돌하는 두 번째 플랫폼 (3BSD 이후)을 만듭니다.
Douglas Leeder

2
내가 올바르게 기억한다면 Palm에는 C Standard Library가 존재하지 않았습니다. 대신 표준 라이브러리 호출을 Palm OS SDK에 매핑 한 대부분 지원되지 않는 헤더 파일이있었습니다. 많은 것들이 예기치 않게 행동했습니다. Crashing on NULL은 표준 라이브러리와 비교하여 Palm 도구 상자의 큰 차이점 중 하나였습니다.
Steven Fisher

8
free(ptr);
ptr=NULL;
free(ptr);/*This is perfectly safe */

NULL 포인터를 안전하게 삭제할 수 있습니다. 이 경우 아무 작업도 수행되지 않습니다. 즉, free ()는 NULL 포인터에 대해 아무 작업도 수행하지 않습니다.


8

권장 사용법 :

free(ptr);
ptr = NULL;

보다:

man free

     The free() function deallocates the memory allocation pointed to by ptr.
     If ptr is a NULL pointer, no operation is performed.

당신은 포인터 설정하면 NULL이후에 free()호출 할 수 free()다시에를 아무런 작업이 수행되지 않습니다.


3
또한 디버거로 segfault를 발견하는 데 도움이됩니다. p = 0 인 p-> do ()의 segfault는 해제 된 포인터를 사용하는 사람이라는 것이 분명합니다. 디버거에서 p = 0xbfade12를 볼 때 덜 분명합니다. :)
neuro

6

free(NULL)완벽하게 C에 대한 법률뿐만 아니라입니다 delete (void *)0delete[] (void *)0C ++에있는 법률.

BTW, 메모리를 두 번 해제하면 일반적으로 일종의 런타임 오류가 발생하므로 아무것도 손상시키지 않습니다.


2
delete 0C ++에서는 합법적이지 않습니다. delete명시 적으로 포인터 유형의 표현식이 필요합니다. delete형식화 된 널 포인터 값 에 적용 하는 것은 합법적 이지만에는 적용 할 수 없습니다 0(에는 적용하지 않음 NULL).
AnT 2009

1
void*둘 중 하나를 삭제할 수 없습니다 . : P 어떤 소멸자 (들)를 실행해야합니까?
GManNickG 2009

1
@GMan : 널 포인터이면 삭제할 수 있습니다void * .
AnT 2009

알겠습니다. 나는 우리가 특별히 null만을 다루는 것을 잊었습니다.
GManNickG 2009

일반적으로 아무것도 손상시키지 않지만 보장되지는 않습니다. ASLR은 이것을 가능성이 거의 없지만 여전히 불가능하지는 않습니다 buf1=malloc(X); free(buf1);buf2=malloc(X);free(buf1); .-여기서 당신이 운이 좋지 않다면 buf2는 buf1과 정확히 같은 주소를 얻었고 실수로 buf1을 두 번 해제 했으므로 buf1이 해제 된 두 번째에서 실제로는 대소 문자없이 buf2를 조용히 해제했습니다. (즉시적인) 오류 / 충돌 / 무엇이든. (하지만 다음에 buf2를 사용하려고 할 때 여전히 충돌이 발생할 수 있습니다. ASLR에서 실행하는 경우이 시나리오는 거의 발생하지 않습니다.)
hanshenrik

3

free(ptr)경우 C에서 저장입니다 ptr입니다 NULL그러나, 대부분의 사람들이 알지 못하는 일 즉, NULLC64에서 주소 0에, 만일 IO 포트가 : 나는 좋은 구식 예를 0으로 동일하지 않을 필요. 이 포트에 액세스하는 C 프로그램을 작성했다면 값이 0 인 포인터가 필요합니다. 해당 C 라이브러리는 0과 NULL그 사이를 구별해야합니다 .

감사합니다.


흥미로운 사실이 나를 놀라게했다. NULL 포인터 질문 / 답변으로 여행을 떠나야한다는 느낌을 받았습니다.
절지 동물

0

메모리 손상은 아니지만 동작은 구현에 따라 다릅니다. 표준 적으로 법적 코드 여야합니다.


-3

ptr은 일부 메모리 위치를 가리키고 있습니다.

free (ptr) 할 때 기본적으로 메모리 관리자가 0x100을 다른 활동이나 프로세스에 사용할 수 있도록 허용하며 간단히 말하면 자원 할당 해제입니다.

ptr = NULL을 수행하면 ptr이 새 위치를 가리키게됩니다 (NULL이 무엇인지 걱정하지 마십시오). 이렇게하면 0x100 메모리 데이터의 추적을 잃게됩니다. 이것이 메모리 누수입니다.

따라서 유효한 ptr에 ptr = NULL을 사용하는 것은 바람직하지 않습니다.

대신 다음을 사용하여 몇 가지 안전한 검사를 수행 할 수 있습니다.

if (ptr! = NULL) {free (ptr);}

ptr이 이미 NULL을 가리키는 곳에서 free (ptr)하면 아무 작업도 수행하지 않으므로 안전합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.