3

我有一个关于 GLib 的问题。我想在服务器上下文中使用 GLib,但我不知道如何管理内存: https ://developer.gnome.org/glib/stable/glib-Memory-Allocation.html

如果任何分配内存的调用失败,应用程序就会终止。这也意味着无需检查调用是否成功。

如果我查看源代码,如果 g_malloc 失败,它会调用 g_error:

g_error()

定义 g_error(...)

用于记录错误消息的便捷函数/宏。错误消息总是致命的,导致调用 abort() 来终止应用程序。[...]

但在我的情况下,当我正在开发一个服务器应用程序时,我不希望应用程序退出,我更喜欢作为传统的 malloc 函数,GLib 函数返回 NULL 或指示发生错误的东西。

所以,我的问题是,有办法处理内存不足吗?不建议将 GLib 用于服务器用途的应用程序吗?

如果我看看 man of abort 我可以看到我可以处理信号,但我会让内存不足错误的管理有点痛苦......

abort() 函数会导致程序异常终止,除非信号 SIGABRT 被捕获并且信号处理程序没有返回。

谢谢你的帮助!

4

2 回答 2

3

从缺乏记忆中恢复是非常困难的。原因是它可以被认为是一种终端状态,因为缺乏记忆会在它消失之前持续一段时间。即使对内存不足做出反应(比如通知用户)也可能需要更多内存,例如,构建和发送消息。一个相关的问题是,有些操作系统(至少是 Linux)可能对分配内存过于乐观。当内核意识到内存丢失时,它可能会终止应用程序,即使您的代码正在处理故障。

因此,要么你对整个系统的掌握比一般人更严格,要么你将无法成功处理内存不足错误,在这种情况下,帮助程序库在做什么并不重要。

如果你真的想在仍然使用 glib 的同时控制内存分配,你有部分方法可以做到这一点。不要使用任何 glib 分配函数并使用其他库中的一些。Glib 提供了在必要时接收“免费函数”的函数。例如:

https://developer.gnome.org/glib/2.31/glib-Hash-Tables.html#g-hash-table-new-full

哈希表构造函数接受用于销毁键和值的函数。在您的情况下,数据将使用自定义分配函数进行分配,而哈希数据结构将使用 glib 函数进行分配。

或者,您可以使用 g_try_* 宏来分配内存,因此您仍然使用 glib 分配器,但它不会因错误而中止。同样,这只能部分解决问题。在内部,glib 将隐式调用可能中止的函数,并假定它永远不会在错误时返回。

关于一般问题:服务器在内存不足时崩溃是否有意义?显而易见的答案是否定的,但我无法估计这个答案的理论性。我只能期望服务器系统的大小适合其操作,并拒绝任何可能超过其容量的输入无效,为此,它可能使用哪些库并不重要。

于 2013-06-07T00:46:28.923 回答
1

我可能在这里编辑了一点,但是使用虚拟/逻辑内存的现代趋势(这两个名称都已使用,尽管“逻辑”更明显)确实使知道内存何时耗尽变得非常复杂,尽管我认为可以恢复Linux 中旧的、真实的(RAM + 交换)模型(我将其称为物理模型),其中包含以下内容/etc/sysctl.d/10-no-overcommit.conf

vm.overcommit_memory = 2
vm.overcommit_ratio = 100

这恢复了这样一种哲学的能力,即如果一个程序malloc刚刚失败,该程序很有可能是内存耗尽的真正原因,然后可以退出当前对象的构造,free一路上内存,可能会抱怨用户要求了一些需要太多 RAM 的疯狂东西,并等待下一个请求。在此模型中,大多数 OOM 条件几乎立即解决 - 程序要么应对并可能返回 RAM,要么在尝试使用由malloc.

使用 linux 在 2013 年默认使用的虚拟/逻辑内存模型,这不起作用,因为程序不会发现内存不可用malloc,而是在稍后尝试访问内存时内核最终意识到 RAM 中没有它的位置。这相当于一场灾难,因为系统上的任何程序都可能死掉,而不是主机内存不足的那个。人们可以理解为什么有些 GLib 的人甚至不关心尝试解决这个问题,因为使用逻辑内存模型,它无法修复。

逻辑内存的初衷是允许使用主机一半以上内存的大型程序仍然能够 fork 和 exec 支持程序。它通常仅在具有该特定使用模式的主机上启用。现在在 2013 年,当家庭工作站可以拥有 24+ GiB 的 RAM 时,真的没有任何借口可以在 99% 的时间内启用逻辑内存。默认情况下,它应该在启动时具有 >4 GiB RAM 的主机上被禁用。

反正。因此,如果您想采用老式物理模型方法,请确保您的计算机已启用它,否则测试您的mallocrealloc调用毫无意义。

如果您处于该模型中,请记住 GLib 并没有真正遵循相同的理念(请参阅http://code.google.com/p/chromium/issues/detail?id=51286#c27了解一些人多么疯狂地误入歧途其中是)。任何基于 GLib 的库也可能被同样的态度感染。但是,通过在物理内存模型中使用 GLib 放置您自己的内存处理程序g_mem_set_vtable(),您可能会做一些有趣的事情,然后重试底层malloc。但是,由于在调用您的特殊处理程序时不知道正在构建哪个对象,这有其自身的限制。

于 2013-07-10T23:20:29.220 回答