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?
实际上是一样的。但是,这为您提供了一个重要功能。
假设您正在从网络接收一些数据,并且协议中有一个字段指定了将包含数组的元素发送给您。您可以执行以下操作:
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
将检查该乘法是否溢出,并将防止这种攻击(此错误非常普遍)。