在 Windows 上分配开始失败之前检测内存运行不足

Posted

技术标签:

【中文标题】在 Windows 上分配开始失败之前检测内存运行不足【英文标题】:Detecting memory running low BEFORE allocations start failing on Windows 【发布时间】:2012-08-08 23:04:01 【问题描述】:

我们的应用程序可能会分配大量小对象(取决于用户输入)。有时应用程序会耗尽内存并有效地崩溃。

但是,如果我们知道内存分配变得紧张,就会有一些优先级较低的对象可能被销毁,从而使我们能够优雅地降低用户结果。

在调用“new”实际失败之前,检测进程内存不足的最佳方法是什么?我们可以调用 API 函数,例如 GetProcessWorkingSetSize()GetProcessMemoryInfo(),但是您如何知道何时达到给定机器的限制(例如,最大分配的 80%)?

【问题讨论】:

除非你的磁盘快满了,否则问题不在于机器上的可用内存量(因为你有虚拟的磁盘内存),而是由于这些对象和地址空间碎片可能的内存泄漏。 @AlexeyFrunze 在 32 位 Windows 上,内存分配似乎在 1.5GB 左右开始失败。这不是内存泄漏,我们可以计算所有使用的内存,但我同意你关于碎片的观点。 【参考方案1】: 在启动时,分配内存保留。 然后使用 set_new_handler() 安装一个检测分配失败的钩子。 发生以下情况时: 释放预留空间(这样您就有足够的可用内存来使用)。 运行您的代码以查找并释放低优先级对象。 完成工作后,再次尝试重新分配预留空间(以备下次使用)。 最后返回让原来的分配尝试重试。

【讨论】:

【参考方案2】:

如果它是 32 位进程,那么您需要确保使用的内存不超过 1.6GB,即 2.0GB 的 80%,即您的进程所允许的最大值。调用GlobalMemoryStatusEx 将填充结构MEMORYSTATUSEX.ullAvailVirtual,当它只有400MB 可用(或更少)时,您就处于阈值。

【讨论】:

【参考方案3】:

检查这个答案Win32/MFC: How to find free memory (RAM) available?。

您需要定期查找可用的空闲内存并在某个限制处停止分配。 如上面提到的答案所述,您可以使用GlobalMemoryStatusEx 和/或VirtualQueryEx

【讨论】:

通常不是一个好主意。见blogs.msdn.com/b/oldnewthing/archive/2012/01/18/10257834.aspx @HarryJohnston 好点。但这是问题还是这个特定的答案? 我认为我们的问题略有不同。我们不关心全局系统资源,我们只想知道操作系统何时将停止分配我们的程序内存,以便我们可以在为时已晚之前采取措施。

以上是关于在 Windows 上分配开始失败之前检测内存运行不足的主要内容,如果未能解决你的问题,请参考以下文章

使用UMDH检测内存泄漏

运行10天后,我的风暴拓扑失败了

WSL2 上的设备内存分配失败

Android 4.0.3 模拟器崩溃:分配内存失败:8

分配内存失败:8 (NetBeans)

cudaMemcpy 仍然无法托管设备分配的内存?