2014-05-20 3 views
2

사례 1 :왜 malloc (LONG_MAX)은 불평하지만 malloc (ULLONG_MAX)은 그렇지 않습니까?

#include <stdlib.h> 
#include <limits.h> 

int main() 
{ 
    void *mem = malloc(ULLONG_MAX); /* or ULONG_MAX */ 

    return 0;  
} 

사례 2 :

#include <stdlib.h> 
#include <limits.h> 

int main() 
{ 
    void *mem = malloc(LLONG_MAX); /* or LONG_MAX */ 

    return 0;  
} 

두 경우는 NULL 포인터를 반환하고 예상대로 12 (ENOMEM) errno를 설정한다. 그런 일이 왜 ULLONG_MAX이

시스템은 맥 OS X 10.8.5입니다 LONG_MAX보다 큰 있기 때문에

long(5072) malloc: *** mmap(size=9223372036854775808) failed (error code=12) *** error: can't allocate region *** set a breakpoint in malloc_error_break to debug

난 그냥 궁금 해서요, 애플 LLVM :하지만 후자, 실제로 메모리 부족에 대한 불만 버전 5.1 (clang-503.0.40)

+6

은'ULLONG_MAX' 아마도 '에 대한 수용 가능한 수에 오버 플로우 malloc'. –

+1

'malloc()'은'ULLONG_MAX'에서 실패 할 수 있습니다. 왜냐하면 시스템은 그것이 처리 할 수있는 어떤 상황보다도 빠르다는 것을 알고 있기 때문입니다. 'LLONG_MAX'의 값이 작을수록 _might_work로 인식하고 할당을 시도하기 시작합니다. 실패한 이유는 다른 이유 때문입니다. 주 : 모든 할당은 'size_t'유형의 'N + 1'에 대한 색인을 허용해야하며 'ULLONG_MAX + 1'이 (가) 오버 플로우 할 수 있습니다. – chux

+0

@RedAlert'sizeof (size_t)! = sizeof (unsigned long long)'이있는 시스템/컴파일러 조합에서도'malloc()'에 넘겨지는 숫자가 넘쳐 흐르지 않습니다. ;-) –

답변

3

malloc의 인수는 부호가없는 유형 인 size_t입니다.

mmap에 대한 오류 메시지에서 malloc이 64 비트 크기로 작동하고 있음을 알 수 있습니다. 실제로 size_tunsigned long long과 같은 유형일 가능성이 큽니다.

즉, 오버플로없이 ULLONG_MAX 값을 나타낼 수 있습니다. 또한 약 절반 인 LLONG_MAX 값을 나타낼 수도 있습니다.

malloc 함수에는 아마도 2 ** 64-1 바이트를 요청할 때 실제로 mmap 요청을 발행하지 못하도록 차단하는 일부 세이프 가드 논리가 포함되어있을 수 있습니다. 메모리를 할당하려고 시도하지 않고도 장애가 발생할 수 있습니다. 그러나 "단지"2 ** 63-1 바이트를 요청하면 mmap을 발행하므로 요청이 커널에서 실패하여 커널 로그 메시지가 발생합니다.

malloc(ULLONG_MAX - 1)을 사용하여 보호 장치가 가능한 가장 높은 64 비트 부호없는 값만 사용하는지 아니면 거기에서 더 낮은 범위까지 확장하는지 여부를 확인하십시오.

malloc은 최대 값 인 size_t에 가까운 크기 범위를 거부하는 것이 합리적입니다. 이러한 크기는 순환 오류를 초래 한 계산 오류의 결과 일 수 있기 때문입니다.

은 (물론, size_t 16 비트 인 작은 시스템 malloc 수 없어 : 프로그램 65535 바이트를 요구한다면, 그것은 아마를 의미한다.)