3

是否可以在通话前“保留”内存malloc()?换句话说,我可以做一些事情(可能是特定于操作系统的)来确保有一定数量的可用内存,以便您知道您的下一个malloc()(或realloc()等)调用不会由于内存不足而返回 NULL 吗?

“保留”或“预分配”可能会像 malloc 一样失败,但如果成功,我想确保我的下一个 malloc() 成功。

笔记:

  • 是的,我知道,我想在分配内存之前分配内存。这是完全正确的。问题是后来的分配并没有真正在我的控制之下,我希望能够假设它们成功了。
  • 关于多线程代码的答案也有加分。
  • 我的动机:我正在考虑在我的 C 开发中采用glibabort() ,但显然它是在它无法分配内存的时候,这对我来说是不可接受的。
  • 也许是一个用其他东西动态替换 malloc 符号的解决方案?或者包装 sbrk 系统调用的函数的符号?
4

4 回答 4

4

使用 glibc,您可以挂钩分配函数:

https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html

现在您控制了程序中的内存分配,您可以做您喜欢的事情,包括编写一个函数来从系统中保留一块(可能是线程本地的,因为您询问了多线程)内存块,以便将来调用您mallocrealloc挂钩将用于返回内存。

malloc显然,您需要以某种方式提前知道您需要不失败的一系列调用将需要多少内存的上限。

于 2013-07-05T13:22:33.497 回答
3

回到旧的 Mac Toolbox 时代,使用一块称为“未雨绸缪”的内存非常普遍。你会分配足够的内存,这样如果你释放它,就会有足够的可用内存来抛出一个对话框,解释应用程序内存不足,保存你的工作,然后退出。然后,您将保留该指针,直到malloc()返回 null,并且至少可以保证您能够优雅地处理它。

不过,那是在一个 100% 的实内存系统上,而现在的情况已经大不相同了。尽管如此,如果我们谈论那些仍然存在的小型且简单的实内存系统,那么类似的策略仍然是有意义的。

于 2013-07-05T13:25:48.897 回答
2

我意识到以下内容并不能直接回答您关于 malloc() 的问题。相反,它试图提供另一种可能适用于您的情况的途径。

几年来,我一直在处理经过认证的嵌入式系统。其中两个限制是 1)我们被禁止释放内存和 2)我们被禁止在初始化过程中分配超过某个点的内存。这是因为动态内存分配和释放可能导致的碎片使得认证成本太高(并保证分配成功)。

我们的解决方案是在早期初始化过程中分配内存池。给定池处理的内存块都将具有相同的大小,从而避免了碎片问题。不同的池会为不同的目的处理不同大小的内存块。这意味着我们必须为最坏的内存消耗情况预先分配足够的内存,并自己管理这些池。

希望这可以帮助。

于 2013-07-05T14:07:03.677 回答
1

显然,您的程序没有什么神奇的方法可以确保您的系统具有任意数量的内存,但是您可以在进程启动后立即获取内存,这样它就不会在工作/一天的中途意外失败。将是一个正确的痛苦。

在某些操作系统上,简单地做一个大的 malloc 然后立即释放内存仍然会调用sbrk或类似的操作系统函数来增加你的进程内存,但即使这样也不是一个很好的解决方案,因为获得虚拟地址空间仍然比获得物理内存要短在需要时支持它,因此您希望使用一些噪声值写入该内存,然后即使它在未使用时被换出到磁盘,您也可以期望系统的虚拟内存满足您的内存需求,而不是拒绝如果系统运行不足,其他程序(或稍后发出的较小的 new/malloc 请求;-P)内存。

另一种方法是寻求特定于操作系统的功能,以坚持将内存页面锁定在物理内存中,例如mlock(2)在 Linux 上。

(一旦一些正在运行的程序都采取这种态度,这种“我是服务器上最重要的东西”的假设往往会使系统变得脆弱......)

于 2013-07-05T13:09:53.530 回答