calloc(10,4)和calloc(1,40)有什么区别?

5
什么是calloc(10,4)和calloc(1,40)之间的区别?
我看到了这种行为:
Thing** things = (Thing**)calloc(1, 10 * sizeof(Thing*));
// things[0] != 0

Thing** things = (Thing**)calloc(10, sizeof(Thing*));
// things[0] == 0

我希望了解为什么。编辑:失去理智是原因,现在两种方法都没有结果...至少让这个问题有趣一些,为什么calloc不像malloc一样只需要一个参数呢?


+1;我自己也曾经想过这个问题。我想知道在所有情况下它是否完全相同;即标准是否要求如此? - Bathsheba
一个(稍微有用的)区别是,calloc(n, sizeof(Thing)) 允许你分配超过 SIZE_MAX 字节的内存,这在理论上是可能的。而 n*sizeof(Thing) 永远不会大于 SIZE_MAX。因此,calloc 在理论上可以用来分配比 malloc 更多的内存。 - Lundin
4个回答

11
在实际应用中,情况是一样的。但这会给你带来一个重要的特性。比如说,当你从网络接收到一些数据时,协议中有一个字段指定了将要发送给你的数组包含多少个元素。你可以这样做:
uint32_t n = read_number_of_array_elements_from_network(conn);
struct element *el = malloc(n * sizeof(*el));
if (el == NULL)
    return -1;
read_array_elements_from_network(conn, el, n);

这看起来很无害,不是吗?但事实并非如此。连接的另一端是恶意的,并将一个非常大的数字作为元素数量发送给您,以使乘法出现包装。假设sizeof(*el)为4,而n读取为2^30+1。乘法2^30+1 * 4将进行包装,结果变为4,这就是您分配的内存,而您已告诉函数要读取2^30+1个元素。 read_array_elements_from_network函数会迅速溢出您分配的数组。 任何体面的calloc实现都会检查这种乘法溢出并保护您免遭此类攻击(该错误非常普遍)。

3

它是相同的。分配内存时,将元素数量乘以一个元素的大小来分配所需的大小。

这并不重要,因为它将成为一个块。


1

实际上它们是相同的,因为分配块是连续的。它会分配 number_of_elements * size_of_element,因此 10 个大小为 4 的元素或 1 个大小为 40 的元素最终都会分配 40 个字节。


0

实际上,除了可能发生在非常大的数字上的错误之外,没有任何区别。 - klutt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接