C 在退出时释放所有堆

C 在退出时释放所有堆,c,memory,memory-management,heap-memory,C,Memory,Memory Management,Heap Memory,我的代码中充满了这样的片段: if (!(row = malloc(reading_size))) memory_error(); if (!(unknowns = calloc(terms, sizeof(*unknowns)))) { free(row); memory_error(); } // ... if (!(unknowns = realloc(unknowns, (terms += TERMS) * sizeof(*unknowns)))) { fre

我的代码中充满了这样的片段:

if (!(row = malloc(reading_size))) memory_error();
if (!(unknowns = calloc(terms, sizeof(*unknowns)))) {
    free(row);
    memory_error();
}

// ...

if (!(unknowns = realloc(unknowns, (terms += TERMS) * sizeof(*unknowns)))) {
    free(row);
    free(unknowns);
    memory_error();
}
它使代码变得相当混乱。现在,值得吗?如果内存分配失败,我真的不认为有必要释放一些其他变量

顺便说一下,函数
memory\u error()
没有什么特别之处:

void memory_error(void) {
    puts("Could not allocate memory.");
    exit(EXIT_FAILURE);
}
或者,是否有一种解决方案可以在退出时释放所有堆?有人建议我做以下工作:

  • 围绕
    malloc()
    calloc()
    realloc()
    编写包装,在我的包装中处理它们的故障
  • 以灵活的数据结构跟踪分配的内存
  • 使用
    atexit()
    注册一个函数,该函数将清除所有分配的内存(利用上述数据结构)
我不是很确定这一点,因为所有的释放都会在出口处完成,所以无论如何这是毫无意义的。据我所知,如果你在不需要内存的情况下尽快释放内存,那么释放内存是很重要的


在这种情况下,最好的做法是什么?

错误恢复有时最好使用
goto
语句处理

if (!(row = malloc(reading_size))) {
    goto error_row;
}
if (!(unknowns = calloc(terms, sizeof(*unknowns)))) {
    goto error_unknowns1;
}

// ...

if (!(unknowns = realloc(unknowns, (terms += TERMS) * sizeof(*unknowns)))) {
    goto error_unknowns2;
}

error_unknowns2:
    free(unknowns);
error_unknowns1:
    free(row);
error_row:
    memory_error();

goto
语句用于无法导致注销的情况下,仅注销在情况恶化之前已成功注册的设施。

您可以自己创建一个:@Bathsheba我曾考虑过GC,但我认为这对我的项目来说是一个过度。这是一个命令行实用程序,所以可能不会发生内存泄漏,但我对最佳实践很感兴趣。就我个人而言,我只想让程序流程保持清晰和正确,就像您目前所做的那样。如果适当的话,可以考虑分配一个<代码>结构> <代码> s的数组。如果您在第一个内存分配错误上退出,则不必费心释放所有成功调用的内存。无论如何,这将由操作系统负责(如果你在一个有堆的平台上的话)。在退出时释放所有堆,给Lilyth镀金这不是一个坏主意,但你可能想解释一下为什么在这种情况下皱眉头的
goto
是可以接受的。通常,在答案中使用
goto
肯定会被否决。这是因为
goto
很容易被误用。或者标签错误:最近的OpenSSL失败是由于使用了goto来误导标签(标签名为
fail
,但实际上没有使功能失败,因为它只执行了清理)。但是在C中,它是C++析构函数的好替代品。<>代码> Goto >到处都是结构化编程概念不支持这种情况。这是错误处理中经常出现的情况。另一个允许
goto
的点是嵌套循环的出口。