【问题标题】:C - Calloc instead of Malloc to save lines?C - Calloc 而不是 Malloc 来保存行?
【发布时间】:2016-08-24 14:42:12
【问题描述】:

我只是想再次检查以下是否完全正常且值得赞赏的改进:

如果我有:

struct ll_Node
{
    void *data;
    struct ll_Node *next, *prev;
};

我有构造函数:

static struct ll_Node* ll_Node_new(void *data)
{
    struct ll_Node *node = calloc(1, sizeof(struct ll_Node));
    if (node == NULL)
        exit(EXIT_FAILURE);
    node->data = data;
    return node;
}

在上面的代码 sn-p 中,我想确保将 previous 变量设置为 NULL。我听说在内存中使用calloc 默认变量为0,这在C 中与NULL 完全相同。

所以代替:

struct ll_Node *node = malloc(sizeof(struct ll_Node));

我愿意

struct ll_Node *node = calloc(1, sizeof(struct ll_Node));

我问这个是因为calloc 似乎在数组 中非常受欢迎,因为如果您将malloc 用于数组,每个项目中都会包含垃圾数据.在第一个参数槽中使用calloc1 是否被认为是错误编码?


微小的子问题:如果我使用calloc 的东西是NULL 可以接受的,是否正在退出程序?或者这有点极端?我认为如果没有剩余内存来创建结构,那么显然我的程序继续运行的任何希望都将被放弃。

【问题讨论】:

  • 空指针可能不会将所有位都设置为零,因此如果您正在编写可移植代码,那么 calloc 就是一个陷阱。
  • @LPs 既然程序已经快要终止了,为什么还要手动释放内存呢?无论如何,操作系统都会这样做。
  • OT:编码struct ll_Node *node = calloc(1, sizeof *node); 更健壮。
  • @bolov 你假设一个,让我说,hi-level 操作系统。我没有;)
  • 即使malloccalloc 没有错误,您打算如何删除/插入/查找节点、清除整个列表等?每个链接链接的实现都应该有这些函数调用;您已经必须跟踪您创建的每个节点,或者您在做什么?那么如果malloc出错了,你想清理退出,应该像delete_list(); exit(errCode);一样简单

标签: c memory-management malloc


【解决方案1】:

您的问题的答案可能都归结为风格。

虽然您使用 calloc 是正确的,以确保分配的内存被清零,尤其是在这种情况下,您在构造节点时没有分配所有字段,但我不喜欢您依赖 calloc 设置 0而不是专门分配 prev 和 next 到 NULL。您必须考虑其他人(甚至您)在 6 个月后阅读此代码。由于没有明确地将 prev 和 next 赋值为 NULL,因此代码的意图稍微不太清楚。

类似这样的:

static struct ll_Node* ll_Node_new(void *data)
{
    struct ll_Node *node = calloc(1, sizeof(struct ll_Node));
    if (node == NULL) {
        exit(EXIT_FAILURE);
    }
    node->data = data;
    node->prev = node->next = NULL;
    return node;
}

让读者清楚 prev 和 next 被初始化为 NULL 并且调用者应该确保它们被设置为正确的值。阅读代码的次数将多于编写的次数,因此您可以采取任何措施来明确代码的意图,从而减轻阅读者的压力。

至于您的其他问题,我同意评论者的观点,如果您的函数返回并且您在一个地方验证该函数是否成功并执行任何通知(设置错误字符串/代码)和清理,则更可取(干净地释放资源)在一个位置是必要的。

【讨论】:

  • 感谢您的建议。我实际上不知道你可以在同一行上做多个作业。这真的很酷!
【解决方案2】:

使用calloc(1, sz) 是完全可以接受的,实际上比malloc(sz) 后跟memset 更可取。 See here for further reading.

但是,假设calloc 生成空指针有点草率。虽然在最流行的现代平台上确实如此,但在过去(甚至可能仍然存在)存在空指针具有其他位模式的平台。

为了尽可能正确,最好先调用 calloc,然后显式设置任何指向 NULL 的指针。如果你在一个空指针实际上全为零的平台上,那么编译器将优化这些分配。

【讨论】:

    猜你喜欢
    • 2011-05-13
    • 2012-03-02
    • 2018-05-28
    • 1970-01-01
    • 1970-01-01
    • 2021-02-08
    • 1970-01-01
    • 2017-05-06
    • 2014-06-28
    相关资源
    最近更新 更多