GLib处理内存不足

时间:2013-06-07 00:10:31

标签: c memory glib

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

  

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

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

  

g_error()

     

定义g_error(...)

     

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

但在我的情况下,由于我正在开发一个服务器应用程序,我不希望应用程序退出,我更喜欢,因为传统的malloc函数,GLib函数返回NULL或者某些东西来指示发生错误。< / p>

所以,我的问题是,有一种处理内存不足的方法吗? GLib不推荐用于服务器用途的应用程序吗?

如果我看看中止的人,我可以看到我可以处理信号,但我会让内存错误的管理有点痛苦......

  

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

谢谢你的帮助!

2 个答案:

答案 0 :(得分: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将隐式调用可能中止的函数,并假设它永远不会返回错误。

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

答案 1 :(得分:1)

我可能在这里进行了一些编辑,但是使用虚拟/逻辑内存的现代趋势(两个名称都被使用,虽然“逻辑”更加明显)确实使得知道何时内存耗尽会很复杂,尽管我认为可以在/etc/sysctl.d/10-no-overcommit.conf中使用以下内容恢复Linux中旧的,真实的(RAM +交换)模型(我称之为物理模型):

vm.overcommit_memory = 2
vm.overcommit_ratio = 100

这恢复了这样一种理念:如果一个程序的malloc失败了,该程序很可能成为内存耗尽的真正原因,然后可以从当前的构造中退出对象,free沿途的记忆,可能抱怨用户要求疯狂的东西,需要太多的RAM,等待下一个请求。在这个模型中,大多数OOM条件几乎立即解决 - 程序要么应对并且可能返回RAM,要么在尝试使用malloc返回的0时立即在后面的SEGV上被杀死。

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

逻辑内存的最初要点是允许使用超过主机内存一半以上的大型程序仍然可以分叉和执行支持程序。它通常仅在具有该特定使用模式的主机上启用。现在在2013年,当一个家庭工作站可以拥有24+ GiB的RAM时,真的没有理由在99%的时间内启用逻辑内存。默认情况下,它应该在启动时具有&gt; 4 GiB RAM的主机上禁用。

反正。因此,如果您想采用老派的物理模型方法,请确保您的计算机已启用,或者没有必要测试您的mallocrealloc来电。

如果 在该模型中,请记住GLib并非真正受到同一哲学的引导(请参阅http://code.google.com/p/chromium/issues/detail?id=51286#c27,了解其中有些是多么疯狂)。基于GLib 的任何库可能也会以同样的态度感染。但是,通过使用g_mem_set_vtable()安装自己的内存处理程序,可以在物理内存模型中使用GLib做一些有趣的事情,因为您可能能够在程序全局中使用并减少缓存中的使用或者喜欢释放空间,然后重试基础malloc。但是,由于在调用特殊处理程序时不知道哪个对象正在构建,因此它以自己的方式受到限制。