calloc()는 SIZE_MAX보다 많이 할당할 수 있습니까?
최근의 코드 리뷰에서, 다음과 같이 주장했습니다.
calloc()보다 더 많이 할당할 수 있습니다.SIZE_MAX총 수: smalloc()제한되어 있습니다.
제 야, calloc()객체 배열을 위한 공간을 만듭니다. 즉, 배열 자체가 객체입니다.그리고 다보다 더큰를 가질 수 없습니다.SIZE_MAX.
그럼 우리 중 누구 말이 맞을까요?의(큰) 일 가능성이 size_t ,calloc()이 }보다큰할 수 .SIZE_MAX?
좀 더 구체적으로 설명하자면, 다음 프로그램은 0이 아닌 상태로 종료될 수 있습니까?
#include <stdint.h>
#include <stdlib.h>
int main()
{
return calloc(SIZE_MAX, 2) != NULL;
}
calloc()는 SIZE_MAX보다 많이 할당할 수 있습니까?
에서"라는 처럼, "에서,calloc()보다 더 많이 할당할 수 있습니다.SIZE_MAX총 수: smalloc()제한적입니다."라는 글을 올린 것으로 저의 근거를 설명하겠습니다.
size_t
size_t적어도 16비트의 부호 없는 유형입니다.
size_t없는 입니다.sizeof자; C11dr§7.192"구현 정의 값은 아래에 제시된 해당 값보다 크기가 같거나 커야 합니다." ...한도의
size_tSIZE_MAX§... 65535 § 7.20.32
의 크기
sizeof단위)를 는 식 가 쳐진 일 수 기위)하며,다§ 6§ .5.3.42
캘록
void *calloc(size_t nmemb, size_t size);
calloc합니다 공간을 할당합니다.nmemb건을 가진size크기 입니다.§7.22.3.2 2
해 보세요.nmemb * size을 훨씬 SIZE_MAX.
size_t alot = SIZE_MAX/2;
double *p = calloc(alot, sizeof *p); // assume `double` is 8 bytes.
한다면calloc()dnmemb * size 및 p != NULL사실입니다. 이것이 위반한 사양은 무엇입니까?
각 요소의 크기(각 개체)를 나타낼 수 있습니다.
// Nicely reports the size of a pointer and an element.
printf("sizeof p:%zu, sizeof *p:%zu\n", sizeof p, sizeof *p);
각 요소는 접근할 수 있습니다.
// Nicely reports the value of an `element` and the address of the element
for (size_t i = 0; i<alot; i++) {
printf("value a[%zu]:%g, address:%p\n", i, p[i], (void*) &p[i]);
}
calloc() 것들
"nmemb개체": 입니다.이것은 확실히 핵심 쟁점입니다.에 = 한에서간 할당"이 =>합니까가 합니까?SIZE_MAX에서 이 로 하는 수 없었기 에 다음과 같이 C 사양에서 이 한계를 필요로 하는 것을 찾을 수 없었기 때문에 다음과 같이 결론지었습니다.
calloc()보다 많은 것을 할당할 수 있습니다.SIZE_MAX
에 대해서는 확실히 드문 일입니다.calloc()비가 아닌으로를 하는 큰 .NULL- 규정에 따르든 안 따르든.일반적으로 이러한 할당은 사용 가능한 메모리를 초과하므로 문제가 발생합니다.제가 만난 유일한 사례는 거대 메모리 모델의 경우였습니다.size_t16비트였고 오브젝트 포인터는 32비트였습니다.
SIZE_MAX라의 합니다를(를) 해야 합니다.size_t, 그것은 반드시 같은 것은 아닙니다.참조: 배열의 최대 크기가 "너무 큰" 이유;
더 큰 잘 되어 있지 SIZE_MAX다를 하는 기능을 합니다.size_t매개 변수.그래서 이론상으로는SIZE_MAX는 극한이고,이고에서는,calloc입니다.SIZE_MAX * SIZE_MAX할당할 바이트입니다.
가가 것.malloc/calloc유형 없이 개체를 할당한다는 것입니다. 않는.SIZE_MAX 이 그러나 이 함수들의 결과가 가리키는 데이터는 종류가 없습니다.아직 배열이 아닙니다.
형식적으로는 데이터에 선언된 유형이 없지만 할당된 데이터 내부에 무언가를 저장하면 저장에 사용되는 데이터 액세스의 유효한 유형을 얻게 됩니다(C17 6.5 §6).
합니다.calloc할당된 것이 (아직) 유형을 가지고 있지 않기 때문에 C의 어떤 유형보다 더 많은 메모리를 할당합니다.
C 한 , C , 에 하게 괜찮습니다.calloc(SIZE_MAX, 2)NULL과 다른 값을 반환하는 것입니다. 할당된 메모리를 어떻게 합리적인 방법으로 실제로 사용할 것인지, 혹은 힙 위에 이렇게 큰 메모리 덩어리까지 지원하는 시스템은 또 다른 이야기입니다.
부터
7.22.3.2 calloc 함수
1#include <stdlib.h> void *calloc(size_t nmemb, size_t size);`
개체의 을 위해 공간을 2 calloc인 nmemb합니다.공간은 모든 비트 0으로 초기화됩니다.
3 calloc는 null합니다.
왜 로 .SIZE_MAX바이트 수
프로그램이 구현 제한을 초과하면 동작이 정의되지 않습니다.이는 구현에 의해 프로그램에 부과되는 제한으로서 구현 한계의 정의에서 따랐습니다(C11의 3.13).표준은 또한 엄격하게 준수하는 프로그램은 구현 한계를 준수해야 한다고 말합니다(C11의 4p5).그러나 이는 일반적으로 프로그램에도 해당됩니다. 왜냐하면 표준은 대부분의 구현 제한을 초과했을 때 어떤 일이 발생하는지를 알려주지 않기 때문입니다(따라서 표준이 어떤 일이 발생하는지 명시하지 않은 다른 종류의 미정의 동작입니다).
표준 역시 어떤 구현 한계가 존재할 수 있는지 규정하지 않아 이는 약간의 백지화이지만, 최대 개체 크기가 개체 할당과 실제로 관련이 있는 것은 타당하다고 생각합니다.(최대 개체 크기는 일반적으로 다음보다 작습니다.SIZE_MAX그건 , 에 포인터의 입니다.char다로 할 수 합니다.ptrdiff_t.)
이를 통해 다음과 같은 관찰을 할 수 있습니다.화에 .calloc (SIZE_MAX, 2)최대 개체 크기 제한을 초과하므로 구현이 표준을 준수하면서 임의의 값을 반환할 수 있습니다.
에서는 실제로 합니다 null 와 합니다.calloc (SIZE_MAX / 2 + 2, 2)다입니다.size_t가치. 이 경우 구현 한계를 쉽게 확인할 수 있고, 오류를 보고할 수 있는 완벽한 방법이 있음을 고려할 때 이 좋은 아이디어가 다른 문제인지 여부.다합니다.calloc구현 버그, 그리고 버그를 봤을 때 구현자에게 보고한 적이 있습니다. 하지만 엄밀히 말하면, 그것은 단지 구현의 품질 문제일 뿐입니다.
스택의 가변 길이 어레이의 경우 구현 제한을 초과하여 정의되지 않은 동작이 발생한다는 규칙이 더 명확합니다.
size_t length = SIZE_MAX / 2 + 2;
short object[length];
구현이 여기서 할 수 있는 일은 사실상 없으므로 정의되지 않아야 합니다.
표준의 본문에 따르면, 아마도 표준이 이러한 종류의 것에 대해 (일부는 의도적으로) 모호하기 때문일 것입니다.
6.5.3.42 당:
sizeof는 해당 기트)합니다의 를 산출합니다.
그리고 7.192 당:
size_t
은 없는 입니다.
sizeof자;
가 () 에서 할 수 포함될 수 .size_t하십시오.calloc"를 모든 "array" 면,다:unsigned char[sizeof object]그것이 그 표현입니다.
보다 큰할 수 SIZE_MAX(또는PTRDIFF_MAX QoI) 않습니다.로) QoI() .코드 검토 시 이러한 잘못된 구현을 고려해야 한다는 주장은 특정 고장 난 C 구현(때로는 임베디드 등과 관련이 있음)과의 호환성을 특별히 보장하려는 것이 아니라면 거짓입니다.
추가 사항:소량의 수학으로 SIZE_MAX * SIZE_MAX = 1(C 규칙에 따라 평가할 경우)을 나타낼 수 있습니다.
그러나 calloc(SIZE_MAX, SIZE_MAX)는 다음 두 가지 중 하나만 수행할 수 있습니다.SIZE_MAX 바이트의 SIZE_MAX 요소 배열에 포인터를 반환하거나 NULL을 반환합니다.인수를 곱하여 1의 결과를 얻고 1바이트를 0으로 할당하는 것만으로 총 크기를 계산하는 것은 허용되지 않습니다.
이 가 같은 형태로 는 아무런 이 없습니다.ptr+number1+number2만,number1+number2을 초과할 입니다.SIZE_MAX 합니다일 .number1+number2gPTRDIFF_MAX인지 C11은 16이라도 32했습니다).ptrdiff_t).
이 표준은 구현이 그러한 큰 객체에 대한 포인터를 생성하는 수단을 제공할 것을 요구하지 않습니다.다를 calloc()수 하며, 합니다, 합니다.calloc()개체를 만들 수 없으면 null 포인터를 반환해야 합니다.
그러나 모든 종류의 개체를 유용하게 할당할 수 있는 기능은 구현 품질 문제입니다.이 하지 않으며,며,부 리눅스다가 할 수 도 않습니다. 는 오버 에 줄 수 있습니다.할 때 할 수 malloc () 한 커밋된다). 물리적 스토리지가 부족할 때 포인터를 사용하려고 하면 치명적인 트랩이 발생할 수 있습니다.입니다의 않은 더 입니다.calloc(x,y)하면 null의 합니다 경우 합니다.x그리고.y해당 바이트 수에 액세스하는 데 사용할 수 없는 포인터를 생성하는 것보다 SIZE_MAX를 초과합니다.표준은합니다에 데 수 있는 를 반환하는지 y적의 x는 각각다를 것으로 .null은 어떤 에서는 불리합니다 각각의 행동은 어떤 상황에서는 유리하고, 어떤 상황에서는 불리합니다.
언급URL : https://stackoverflow.com/questions/52699574/can-calloc-allocate-more-than-size-max-in-total
'programing' 카테고리의 다른 글
| "제출" 콜백을 사용할 때 여러 번 제출한 양식과 $.ajax를 게시합니다. (0) | 2023.10.12 |
|---|---|
| Oracle SQL: 중첩 테이블이 있는 테이블에서 선택 (0) | 2023.10.12 |
| CSS를 사용하여 디브 3개를 나란히 띄우는 방법? (0) | 2023.10.12 |
| Java의 MySQL Insert 문 성능: Batch mode 준비문 vs 여러 값을 가진 단일 insert (0) | 2023.10.12 |
| 다음 형제/X를 선택하는 방법XPath를 사용한 ML 태그 (0) | 2023.10.12 |