处理“内存不足”的正确方法是什么?

时间:2009-09-17 16:41:19

标签: c malloc

最近,我在Windows上制作了一个CCTV节目的视频播放器程序。由于程序必须同时解码和播放许多视频流,我认为它可能会遇到malloc失败的情况,并且我会在每个malloc之后添加检查。

但从整体上讲,在我在开源项目中阅读的这些开源程序代码中,我很少发现对malloc结果的任何检查。所以当malloc失败时,大多数程序都会崩溃。那不是不接受吗?

我在linux上编写服务器程序的同事会为100个客户端连接分配足够的内存。因此,虽然他的程序可能会拒绝101客户端,但它永远不会遇到malloc的失败。他的方法是否也适用于桌面应用程序?

7 个答案:

答案 0 :(得分:12)

在Linux上,malloc()永远不会失败 - 相反,OOM杀手将被触发并开始杀死随机进程,直到系统崩溃。由于Linux是当今最流行的UNIX衍生产品,许多开发人员已经学会了永远不检查malloc()的结果。这可能是你的同事忽视malloc()失败的原因。

在支持失败的操作系统上,我看到了两种一般模式:

  • 编写一个自定义过程,用于检查malloc()的结果,如果分配失败,则调用abort()。例如,GLib and GTK+库使用此方法。

  • 存储“清除”分配的全局列表,例如缓存,可在分配失败时清除。然后,再次尝试分配,如果仍然失败,则通过标准错误报告机制(不执行动态分配)报告它。

答案 1 :(得分:6)

遵循标准化API

即使在Linux上,ulimit也可用于获取malloc错误返回的提示。它只是默认为无限制。

符合公布标准的压力很大。在大多数系统上,从长远来看,最终甚至在Linux上,malloc(3)将返回正确的失败指示。桌面系统确实具有虚拟内存和请求分页,但即使这样,检查malloc(3)也只能在没有内存泄漏的已调试程序中运行。如果出现任何问题,有人会想要设置ulimit并跟踪它。突然,malloc检查是有道理的。

答案 2 :(得分:1)

在没有检查null的情况下使用malloc的结果在可能在malloc可能失败的平台上开放使用的代码中是不可接受的,在这些代码上它往往会导致崩溃和不可预测的行为。我不能预见未来,不知道我的代码将去哪里,所以我会编写带有malloc返回null检查的代码 - 更好地死,而不是表现得不可预测!

如果malloc失败,该怎么办的策略取决于应用程序的类型以及您对所使用的库的信心。在某些情况下,唯一安全的做法是停止整个程序。

如果您的应用程序的内存使用是可预测的,那么预先分配已知的内存配置并在某些块中进行分配的想法,因此转向实际上耗尽了内存是一个很好的想法。您可以将其扩展为编写自己的内存管理例程以供代码使用。

答案 3 :(得分:1)

这取决于您正在处理的应用程序类型。如果应用程序的工作分为可以允许单个任务失败的离散任务,则可以优雅地恢复检查内存分配。

但在许多情况下,响应malloc失败的唯一合理方法是终止程序。允许您的代码在不可避免的空取消引用上崩溃将实现这一点。转储日志条目或解释错误的错误消息肯定总是更好,但在现实世界中,我们在有限的时间表上工作。有时迂腐错误处理的投资回报不存在。

答案 4 :(得分:0)

在这种情况下,请始终检查并预先分配可以释放的缓冲区,以便警告用户保存其数据并关闭应用程序。

答案 5 :(得分:0)

取决于您编写的应用程序。当然,您总是需要检查malloc()的返回值。但是,优雅地处理OOM仅在某些情况下才有意义,例如低级别的关键系统服务,或者在编写可能被使用的库时。因此,在许多应用程序和框架中,使用在OOM上中止的malloc包装器非常常见。这些包装器通常被命名为xmalloc()或类似的。

GLib的g_malloc()也正在中止。

答案 6 :(得分:0)

如果你要处理大量的内存,并希望向Linux发表声明,“现在我有内存区ABC,我不需要B片,按你的意愿去做”,看看mmap ()/ madvise()库存GNU C库中可用的函数系列。根据您的使用模式,代码最终可能比使用malloc更简单。此API还可用于帮助Linux不会通过缓存您将要读/写一次的文件来浪费内存。

在GNU libc info文档中很好地记录了它们。