【问题标题】:Should you free at the end of a C program [duplicate]您是否应该在 C 程序结束时释放 [重复]
【发布时间】:2018-07-03 23:52:32
【问题描述】:

假设我有一个类似下面的程序

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
  if (argc < 2) return 1;
  long buflen = atol(argv[1]);
  char *buf = malloc(buflen);
  fread(buf, 1, buflen, stdin);

  // Do stuff with buf

  free(buf);
  return 0;
}

此类程序通常具有更复杂的清理代码,通常包括对free 的多次调用,有时还包括用于错误处理的标签甚至清理函数。

我的问题是:最后的free(buf) 真的有必要吗?我的理解是,程序退出时内核会自动清理未释放的内存,但如果是这样,为什么在代码末尾放 free 这么常见的模式?

BusyBox 提供了一个编译选项,可以在执行结束时禁用免费调用。如果这不是问题,那么为什么有人会禁用该选项?纯粹是因为像 Valgrind 这样的程序会在分配的内存没有释放时检测到内存泄漏吗?

【问题讨论】:

  • 有必要吗?在大多数情况下没有。但自己打扫卫生是个好习惯。
  • 要添加到前面的评论,假设您使用不同的小程序(例如您的示例)一起构建另一个更大的程序/应用程序。或者以某种方式将它变成一个持续运行并多次执行您的功能的守护程序。如果您没有添加任何free,则在将各个部分组合在一起/使其循环运行时很容易忘记添加它。现在你的程序有严重的内存泄漏。

标签: c memory-management


【解决方案1】:

实际上,绝对如此?在现代操作系统上,没有。在一些环境中,是的。

清理您分配的所有内容始终是一个好计划,因为这样可以很容易地扫描内存泄漏。如果您在退出之前有未完成的分配,那么您就有泄漏。如果你不free 事情是因为操作系统为你做的,那么你不知道这是一个错误还是预期的行为。

您还应该检查任何可能返回错误的函数,例如fread,但您不这样做,因此您已经牢牢地处于危险区域。这个关键任务代码是否会在崩溃时发生坏事?如果是这样,您将希望完全按照书本行事。

正如 Jean-François 所指出的,这种琐碎代码的组成方式是一个不好的例子。大多数程序看起来更像这样:

void do_stuff_with_buf(char* arg) {
  long buflen = atol(arg);
  char *buf = malloc(buflen);
  fread(buf, 1, buflen, stdin);

  // Do stuff with buf

  free(buf);
}

int main(int argc, char *argv[]) {
  if (argc < 2)
    return 1;

  do_stuff_with_buf(argv[1])

  return 0;
}

这里应该更明显的是do_stuff_with_buf函数应该自己清理,它不能依赖程序退出来释放资源。如果多次调用该函数,则不应泄漏内存,那只是草率,可能会导致严重问题。失控的分配可能会导致诸如臭名昭著的 Linux“OOM 杀手”之类的东西出现并继续大肆谋杀以释放一些内存,这通常只会导致混乱和混乱。

【讨论】:

  • 关于检查来自fread 的错误的要点。这只是一个示例,而不是实际代码。
  • 以 AmigaOS 为例。它没有资源跟踪。如果您不释放内存,则在重新启动之前不会得到它(使用 ctrl+A+A :))
  • 太棒了,感谢您提供额外的细节!
  • 另一个原因:如果有一天你将你的 main 变成一个服务/无限循环,你会很高兴你正确地处理了释放。
  • @Jean-FrançoisFabre 或者使用 valgrind --leak-kinds=all,如果你的操作系统支持的话。
猜你喜欢
  • 2014-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-25
  • 1970-01-01
  • 2011-09-14
  • 1970-01-01
相关资源
最近更新 更多