你应该在 C 程序结束时释放吗

Sam*_*adi 1 c memory-management

假设我有一个如下所示的程序

#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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

tad*_*man 5

实际上,就像绝对一样?在现代操作系统上,没有。在某些环境下,是的。

\n\n

清理分配的所有内容始终是一个好计划,因为这使得扫描内存泄漏变得非常容易。如果您在退出之前有未完成的分配,那么您就会出现泄漏。如果你不做free事情是因为操作系统为你做的,那么你不知道这是错误还是有意的行为。

\n\n

您还应该检查任何可能返回错误的函数(例如 )中的错误fread,但您没有这样做,因此您已经牢牢处于危险区域中。如果这段关键任务代码崩溃了,会发生什么坏事吗?如果是这样,您将希望完全按照书本行事。

\n\n

正如 Jean-Fran\xc3\xa7ois 指出的那样,这段简单代码的组成方式是一个坏例子。大多数程序看起来更像这样:

\n\n
void do_stuff_with_buf(char* arg) {\n  long buflen = atol(arg);\n  char *buf = malloc(buflen);\n  fread(buf, 1, buflen, stdin);\n\n  // Do stuff with buf\n\n  free(buf);\n}\n\nint main(int argc, char *argv[]) {\n  if (argc < 2)\n    return 1;\n\n  do_stuff_with_buf(argv[1])\n\n  return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n

  • 以 AmigaOS 为例。它没有资源跟踪。如果您不释放内存,则在重新启动之前您不会获得它(使用 ctrl+A+A :)) (2认同)
  • @Jean-FrançoisFabre 或者使用 valgrind `--leak-kinds=all` 如果您的操作系统支持的话。 (2认同)

归档时间:

查看次数:

1777 次

最近记录:

8 年,4 月 前