calloc()
能否分配超过SIZE_MAX
的总字节数?
由于断言“在某些系统上,calloc()
可以分配超过SIZE_MAX
的总字节数,而malloc()
受到限制。”来自我发布的评论,我将解释我的理由。
size_t
size_t
是至少16位的一些无符号类型。
size_t
是sizeof
运算符的结果的无符号整数类型;C11dr §7.19 2
“其实现定义值应等于或大于以下给定值的相应值”...size_t
的极限值SIZE_MAX
... 65535 §7.20.3 2
sizeof
sizeof
运算符返回其操作数的大小(以字节为单位),操作数可以是表达式或类型的括号名称。§6.5.3.4 2
calloc
void *calloc(size_t nmemb, size_t size);
calloc
函数为一个大小为nmemb*size
的数组分配空间,其中每个对象的大小为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()真正分配了nmemb * 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
通常是不常见的 - 不管是否符合规范。通常这种分配会超出可用的内存,所以这个问题就没了。 我遇到的唯一情况是在Huge memory model中,其中size_t
为16位,对象指针为32位。
size_t
可以表示任何对象的规则。 - Toby Speight