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

Nat*_*teS 3 c calloc

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
Run Code Online (Sandbox Code Playgroud)

我想知道为什么。编辑:失去理智是为什么,两者现在似乎都导致零...至少使问题变得有趣,为什么calloc不能只接受单个参数,例如malloc?

Art*_*Art 5

实际上是一样的。但是,这为您提供了一个重要功能。

假设您正在从网络接收一些数据,并且协议中有一个字段指定了将包含数组的元素发送给您。您可以执行以下操作:

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);
Run Code Online (Sandbox Code Playgroud)

这看起来无害,不是吗?好吧,不是那么快。连接的另一面是邪恶的,实际上向您发送了非常多的元素数量,以便乘法运算得到包裹。假设这sizeof(*el)是4,而n读取为2^30+1。乘法2^30+1 * 4换行,结果变为4,这就是您告诉函数读取2 ^ 30 + 1元素时所分配的。该read_array_elements_from_network函数将快速溢出您分配的数组。

任何体面的实现都calloc将检查该乘法是否溢出,并将防止这种攻击(此错误非常普遍)。