【问题标题】:What is the difference between calloc(10,4) and calloc(1,40)?calloc(10,4) 和 calloc(1,40) 有什么区别?
【发布时间】:2013-09-26 06:48:46
【问题描述】:

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;我自己也想过这个。我想知道它是否在所有情况下都完全相同;即标准是否规定了这一点?
  • 一个(稍微有用的)区别是calloc(n, sizeof(Thing)) 允许您分配超过SIZE_MAX 字节,这在理论上是可能的。而n*sizeof(Thing) 永远不能大于SIZE_MAX。因此calloc 理论上可以用于分配比malloc 允许的更多的内存。

标签: c calloc


【解决方案1】:

实际上是一样的。但它为您提供了一项重要功能。

假设您正在从网络接收一些数据,并且协议有一个字段,该字段指定数组将包含多少个元素将发送给您。你可以这样做:

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 的任何体面实现都会在该乘法中检查溢出并防止此类攻击(此错误非常常见)。

【讨论】:

    【解决方案2】:

    是一样的。分配将元素数量乘以一个元素的大小来分配大小。

    没关系,因为它会是一个块。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        calloc(10,4) 将分配 10 个大小为 4 的元素,而 calloc(1,40) 将分配一个大小为 40 的元素。

        参考:http://www.tutorialspoint.com/c_standard_library/c_function_calloc.htm

        我的意思是每个分配的元素。

        【讨论】:

        • 在实践中绝对没有区别,除了非常大的数字可能发生的错误。
        猜你喜欢
        • 2010-12-05
        • 2012-05-28
        • 2017-09-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多