malloc (0)의 요점은 무엇입니까?


답변:


121

사양에 따르면 malloc (0) 은 "널 포인터 또는 free ()에 성공적으로 전달할 수있는 고유 포인터"를 반환합니다.

이렇게하면 기본적으로 아무것도 할당 할 수 없지만 걱정없이 "artist"변수를 free () 호출에 전달할 수 있습니다. 실용적인 목적을 위해 다음을 수행하는 것과 거의 동일합니다.

artist = NULL;

51
개인적으로, NULL로 설정하는 것이 더 나은 크로스 플랫폼 전략이라고 생각합니다. free ()가 (사양에 따라) 입력으로 NULL에서 잘 작동하도록 보장되기 때문입니다.
Reed Copsey

2
C. Ross가 언급했듯이 일부 플랫폼은 기술적으로 여기에 포인터를 반환 할 수 있지만 (즉, "자유롭게 전달할 수있는 고유 한 포인터"), 이것을 char *로 취급하면 유효하지 않은 종료되지 않은 문자입니다. 크로스 플랫폼 상황에서 이것에 의존하는 것은 위험 할 수 있습니다.
Reed Copsey

9
정말 사양이 잘 -.-으로 "안전 realloc을 전달"말할 텐데
hanshenrik

1
@NSAddict "sizeof가 0을 반환하는 빈 구조체", 예제를 제공하십시오. 언어 확장처럼 들립니다.
chux - 분석 재개 모니카

1
@hanshenrik 누가 할 수 없다고? realloc()에서 반환 한 유효한 포인터를 전달할 수 있습니다 malloc(). 충분해야합니다.
glglgl

51

C 표준 (C17 7.22.3 / 1)은 다음과 같이 말합니다.

요청 된 공간의 크기가 0이면 동작은 정의 된 구현입니다. null 포인터가 반환되거나 반환 된 포인터가 개체에 액세스하는 데 사용되지 않는 것을 제외하고는 크기가 0이 아닌 값인 것처럼 동작합니다.

따라서 역 참조되지 않을 수 있는 유효한 포인터 또는 malloc(0)반환 할 수 있습니다 . 두 경우 모두 전화하는 것이 완벽하게 유효합니다.NULLfree() 하는 것이 합니다.

예를 들어 루프에서 호출되는 malloc(0)경우를 제외하고는 실제로 많이 사용 되지 않는다고 생각합니다.malloc(n)n 0 일 수 합니다.

링크의 코드를 보면 저자가 두 가지 오해를 가지고 있다고 생각합니다.

  • malloc(0)항상 유효한 포인터를 반환 하고
  • free(0) 나쁘다.

그래서 그는 artist다른 변수들에 항상 "유효한"값이 있는지 확인 했습니다. 댓글은 다음과 같이 말합니다 // these must always point at malloc'd data.


10
이것이 구현에 의존적이라는 사실은 그것을 다소 완전히 쓸모 없게 만듭니다. 이것은 C 표준의 끔찍한 부분 중 하나이며 표준위원회 (예 : PJ Plauger) 중 상당수가 그것에 대해 신음했습니다.

10
나는 동의한다. 경우 malloc(0)유효한 포인터를 반환하고 malloc()반환 NULL항상 "실패"를 의미하고, 0일관성있는, 더 이상 특별한 경우가 아니다.
Alok Singhal

1
malloc메모리를 얻지 못하는 상황 은 구현에 따라 정의되므로 구현에서는 크기 0 할당이 항상 만족스럽지 ENOMEM않으며 ( ), 이제 malloc(0)0 (와 함께 errno==ENOMEM)을 반환하는 것이 일관성이 있다고 정의 할 수 있습니다. :-)
R .. GitHub의 STOP 돕기 ICE

6
realloc의해 반환 된 포인터 수 있습니까 malloc(0)? 당신은 할 수 realloc((char*)NULL)있습니까?
Braden Best

3
@Braden Best 둘 다 예.
chux - 분석 재개 모니카

11

malloc (0) 동작은 구현에 따라 다릅니다. 라이브러리는 NULL을 반환하거나 메모리가 할당되지 않은 일반 malloc 동작을 가질 수 있습니다. 무엇을하든 어딘가에 문서화해야합니다.

일반적으로 유효하고 고유하지만 역 참조해서는 안되는 포인터를 반환합니다. 또한 실제로 아무것도 할당하지 않았더라도 메모리를 소비 할 수 있습니다.

널이 아닌 malloc (0) 포인터를 재 할당 할 수 있습니다.

하지만 malloc (0)을 그대로 사용하는 것은별로 유용하지 않습니다. 동적 할당이 0 바이트이고 유효성을 검사 할 필요가 없을 때 주로 사용됩니다.


9
malloc()"하우스 키핑 정보"를 어딘가에 보관해야합니다 (예 : 할당 된 블록의이 크기 및 기타 보조 데이터). 따라서를 반환 malloc(0)하지 않으면 NULL해당 정보를 저장하는 데 메모리를 사용하고, 그렇지 않으면 free()메모리 누수를 구성합니다.
Alok Singhal

Malloc 구현은 요청 된 크기 위에 반환 된 포인터 당 특정 양의 데이터를 추가 할 수있는 레코드 보관을 수행합니다.
user7116 2010 년

1
사용 된 메모리와 할당 된 메모리는 같은 의미가 아닙니다. 이 경우 대부분의 구현은 고유 한 포인터를 반환합니다. 이는 해당 포인터를 위해 주소 공간의 일부를 희생해야 함을 의미합니다. 할당 자에 따라 이것은 실제로 1 바이트 이상을 할당한다는 것을 의미 할 수 있습니다.
Coincoin

1
라이브러리는 원하는대로 할 수 있습니다. 다른 사람 malloc()이 반환 하지 않는 고유 한 포인터를 반환하거나 NULL.
Alok Singhal

1
@jldupont : 최소한 Microsoft C 런타임 라이브러리는 malloc(0). 그러나 표준 C 라이브러리의 동일한 구현에서 NULL을 realloc(ptr, 0)해제 ptr하고 반환합니다.
Medinoc

5

이 페이지의 다른 곳에서 "malloc (0)은 유효한 메모리 주소를 반환하고 범위는 메모리가 할당되는 포인터의 유형에 따라 달라집니다"로 시작하는 답변이 있습니다. 이 진술은 정확하지 않습니다 (저는 그 대답에 대해 직접 언급 할만한 평판이 충분하지 않으므로이 주석을 바로 아래에 둘 수 없습니다).

malloc (0)을 수행하면 올바른 크기의 메모리가 자동으로 할당 되지 않습니다 . malloc 함수는 결과를 캐스팅하는 대상을 인식하지 못합니다. malloc 함수는 인수로 제공하는 크기 번호에만 의존합니다. 예를 들어 0이 아닌 int를 저장하기에 충분한 저장 공간을 확보하려면 malloc (sizeof (int))을 수행해야합니다.


4

malloc(0)코드가 구현에 특정한 동작에 의존하지 않는 한 나에게 의미가 없습니다. 코드가 이식 가능하도록 의도 된 경우 NULL 반환 malloc(0)이 실패가 아니라는 사실을 고려해야합니다 . 그렇다면 artist유효한 성공적인 결과이고 코드가 적고 유지 보수 프로그래머가 시간을 들여 알아내는 데 시간이 걸리지 않기 때문에 어쨌든 NULL을 할당하지 않는 이유 는 무엇입니까?

malloc(SOME_CONSTANT_THAT_MIGHT_BE_ZERO)또는 malloc(some_variable_which_might_be_zero)값이 0이면 NULL 반환을 실패로 처리하지 않도록 특별히주의해야하지만, 크기가 0이면 괜찮습니다.


3

여기에는 절반 정도의 정답이 있으므로 여기에 어려운 사실이 있습니다. 의 맨 페이지 malloc()내용 :

크기가 0이면 malloc ()은 NULL 또는 나중에 free ()에 성공적으로 전달할 수있는 고유 한 포인터 값을 반환합니다.

즉,의 결과 malloc(0)가 고유하거나 NULL이 아니라는 보장이 전혀 없습니다 . 유일한 보증은의 정의에 의해 제공됩니다 free(). 맨 페이지에 다음과 같은 내용이 있습니다.

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

따라서 malloc(0)반환되는 것이 무엇이든 안전하게 전달할 수 free()있습니다. 그러나 NULL포인터도 마찬가지 입니다.

결과적으로 글쓰기 artist = malloc(0); 는 글쓰기보다 낫지 않습니다. artist = NULL;


1
너무 나쁘게 구현이 null이 아닌 고유하지 않은 포인터를 반환하도록 허용되지 않습니다. 그런 식으로, malloc(0)반환 말, 0x1로, 그리고 수 free()는 0x0으로 위해가 마찬가지로 0x1로의 특별한 경우의 체크를 가질 수있다.
Todd Lehman

3
@Todd Lehman 제안한대로 구현할 수 있습니다. C 스펙은 결과가 " NULL또는 고유 포인터" 여야 함을 지정하지 않습니다 . 대신 '널 포인터 또는 할당 된 공간에 대한 포인터'. 고유 한 요구 사항 이 없습니다 . OTOH, 고유하지 않은 특수 값을 반환하면 고유 값을 계산하는 코드가 중단 될 수 있습니다. SO에 대한 코너 케이스 질문 일 수 있습니다.
chux- 분석 재개 모니카

man* nix에서 사용되는 구현 정의 형식을 문서화 할 수도 있습니다. 이 경우에는 그렇지 않습니다,하지만 여전히 일반 C.에 대한 정식 소스 아니다
룬딘

@Lundin 사실. 그러나 맨 페이지는 C 표준보다 훨씬 더 접근하기 쉽고 GNU / 리눅스 시스템의 맨 페이지는 일반적으로 구현이 따르는 표준을 아주 잘 문서화합니다. 어떤 부품이 어떤 표준을 준수하는지에 대한 정보와 함께 다른 경우. 나는 ... 둘 다 정확하게하려는 느낌이 있고, GNU 확장의 모든 단일 비트를 광고
cmaster - 분석 재개 모니카

3

이걸하면 안되는 이유 ...

malloc의 반환 값은 구현에 따라 다르므로 NULL 포인터 또는 다른 주소를 다시 얻을 수 있습니다. 오류 처리 코드가 크기와 반환 값을 모두 확인하지 않으면 결국 힙 버퍼 오버플로가 발생하여 안정성 문제 (충돌) 또는 더 나쁜 보안 문제가 발생할 수 있습니다.

반환 된 주소를 통해 추가로 메모리에 액세스하면 크기가 0이고 구현이 NULL이 아닌 값을 반환하는 경우 힙이 손상되는이 예를 고려하십시오.

size_t size;

/* Initialize size, possibly by user-controlled input */

int *list = (int *)malloc(size);
if (list == NULL) {
  /* Handle allocation error */
}
else {
  /* Continue processing list */
}

추가 읽기를 위해 위의 예제를 사용한 CERT 코딩 표준 의이 보안 코딩 페이지 를 참조하십시오 .



2

사실, 나는 이것을 본 적이 없다. 이것은 내가이 구문을 본 것은 처음이다. 함수 과잉의 고전적인 경우라고 말할 수있다. Reed의 대답과 관련하여 과부하 된 함수처럼 보이는 비슷한 것이 있음을 지적하고 싶습니다 realloc.

  • foo는 NULL이 아니고 크기는 0 realloc(foo, size);입니다. NULL이 아닌 포인터와 크기 0을 realloc에 ​​전달하면 realloc은 마치 free (…)를 호출 한 것처럼 동작합니다.
  • foo는 NULL이고 크기는 0이 아니고 1보다 큽니다 realloc(foo, size);. NULL 포인터를 전달하고 크기가 0이 아닌 경우 realloc은 malloc (…)을 호출 한 것처럼 작동합니다.

이것이 도움이되기를 바랍니다. 안부, Tom.


1

실제로 질문에 답하기 위해 : 그렇게 할 이유가 없습니다.


0

malloc (0)은 NULL을 반환하거나 올바른 포인터를 해제 할 수 있습니다. 그리고 그것이 가리키는 메모리가 쓸모 없거나 쓰거나 읽을 수없는 것처럼 보이지만 항상 사실은 아닙니다. :)

int *i = malloc(0);
*i = 100;
printf("%d", *i);

여기서 세분화 오류를 예상하지만 놀랍게도 이것은 100을 인쇄합니다! malloc이 처음으로 malloc을 호출 할 때 실제로 많은 양의 메모리를 요청하기 때문입니다. 이후 malloc에 ​​대한 모든 호출은 그 큰 덩어리의 메모리를 사용합니다. 그 거대한 덩어리가 끝난 후에야 새로운 메모리가 요구됩니다.

malloc (0) 사용 : 후속 malloc 호출이 더 빨라지기를 원하는 상황에있는 경우 malloc (0)을 호출해야합니다 (가장자리 경우 제외).


1
*i귀하의 경우에 쓰기가 중단되지 않을 수도 있지만 그럼에도 불구하고 정의되지 않은 동작입니다. 비강 악마를 조심하세요!
John Dvorak

1
예. 사실입니다. 구현에 따라 다릅니다. MaxOS X 및 일부 Linux 배포에서 확인했습니다. 다른 플랫폼에서는 시도하지 않았습니다. 하지만 제가 설명한 개념은 Brain Kernighan과 Dennis Ritchie의 책 "The C programming language"에 설명되어 있습니다.
Sagar Bhosale

나는이 질문에 대해 매우 늦은 코멘트를 알고 있습니다. 그러나 때때로malloc(0) 언급되지 않은 용도 가 있습니다. 특히 DEBUG 빌드에서 NULL이 아닌 값을 반환하는 구현에서는 요청한 것보다 더 많이 할당하고 내부 헤더를 지나칠 수있는 포인터를 제공합니다. 이를 통해 일련의 할당 전후에 이것을 얻을 경우 실제 메모리 사용량에 대한 느낌 을 얻을 수 있습니다 . 예 : void* before = malloc(0); ... void* after = malloc(0); long long total = after - before;또는 일부.
Jesse Chisholm은

Brain Kernighan과 Dennis Ritchie의 "The C programming language"를 읽었는데 malloc(0). 어떤 장을 참조하고 있는지 말씀해 주시겠습니까? 정확한 견적을 제공하는 것도 좋을 것입니다.
Андрей Беньковский

0

Windows에서 :

  • void *p = malloc(0);로컬 힙에 길이가 0 인 버퍼를 할당합니다. 반환 된 포인터는 유효한 힙 포인터입니다.
  • malloc궁극적으로 HeapAlloc기본 C 런타임 힙을 사용하여 호출 한 다음 RtlAllocateHeap, 등 을 호출합니다 .
  • free(p);HeapFree힙에서 길이가 0 인 버퍼를 해제하는 데 사용 합니다. 해제하지 않으면 메모리 누수가 발생합니다.

0

실제로 매우 유용하며 (분명히 IMHO) NULL 포인터를 반환하는 허용되는 동작이 손상되었습니다. 동적 포인터는 가리키는 것뿐만 아니라 주소가 고유하다는 사실에도 유용합니다. NULL을 반환하면 두 번째 속성이 제거됩니다. 내가 프로그램하는 모든 임베디드 malloc (사실상 자주)은이 동작을 가지고 있습니다.



-2

다음은 valgrind 메모리 검사 도구로 실행 한 후의 분석입니다.

==16740== Command: ./malloc0
==16740==
p1 = 0x5204040
==16740==
==16740== HEAP SUMMARY:
==16740==     in use at exit: 0 bytes in 0 blocks
==16740==   total heap usage: 2 allocs, 2 frees, 1,024 bytes allocated
==16740==
==16740== All heap blocks were freed -- no leaks are possible

내 샘플 코드는 다음과 같습니다.

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

int main()
{
   //int i;
   char *p1;

   p1 = (char *)malloc(0);
   printf("p1 = %p\n", p1);

   free(p1);

   return 0;

}

기본적으로 1024 바이트가 할당됩니다. malloc의 크기를 늘리면 할당 된 바이트가 1025만큼 늘어납니다.


-3

Reed Copsey 답변과 malloc man 페이지에 따르면 테스트 할 몇 가지 예제를 작성했습니다. 그리고 malloc (0)이 항상 고유 한 값을 제공한다는 것을 알았습니다. 내 예를 참조하십시오.

char *ptr;
if( (ptr = (char *) malloc(0)) == NULL )
    puts("Got a null pointer");
else
    puts("Got a valid pointer");

출력은 "Got a valid pointer"이며 이는 ptrnull이 아님 을 의미 합니다.


-6

malloc(0)유효한 메모리 주소를 반환하고 범위는 메모리가 할당되는 포인터 유형에 따라 달라집니다. 또한 메모리 영역에 값을 할당 할 수 있지만 사용되는 포인터 유형에 따라 범위 내에 있어야합니다. 할당 된 메모리를 해제 할 수도 있습니다. 예를 들어 설명하겠습니다.

int *p=NULL;
p=(int *)malloc(0);
free(p);

위의 코드는 gccLinux 시스템 의 컴파일러에서 잘 작동합니다 . 32 비트 컴파일러가있는 경우 정수 범위 (예 : -2147483648 ~ 2147483647)의 값을 제공 할 수 있습니다. 문자에도 동일하게 적용됩니다. 선언 된 포인터의 유형이 변경되면 malloctypecast에 관계없이 값의 범위가 변경됩니다.

unsigned char *p=NULL;
p =(char *)malloc(0);
free(p);

p unsigned int로 선언되었으므로 0에서 255까지의 char 값을 사용합니다.


5
Krellan은이 대답이 틀렸다는 점을 지적하는 것이 옳습니다 : malloc()캐스트에 대해 아무것도 알지 못합니다 (실제로 C에서 완전히 능숙 함). 의 반환 값을 역 참조하면 malloc(0)정의되지 않은 동작이 호출됩니다.
cmaster - 분석 재개 모니카

-6

여기에서 잘못된 인상을 수정하려면 :

artist = (char *) malloc(0);결코 돌아 오지 않을 것입니다 NULL; 그것은 artist = NULL;. 간단한 프로그램을 작성하고 비교 artist와 함께 NULL. if (artist == NULL)거짓이고 if (artist)참입니다.

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