我正在编写一个消耗大量内存的缓存应用程序.
希望我能够很好地管理自己的记忆,但是我只是在考虑如果我的内存不足会怎么做.
如果调用甚至分配一个简单的对象失败,即使是syslog调用也可能会失败?
编辑:好的,也许我应该澄清这个问题.如果malloc或new返回NULL或0L值,那么它实质上意味着调用失败,并且由于某种原因它无法为您提供内存.那么,在这种情况下做什么是明智的做法?
EDIT2:我刚刚意识到对"new"的调用会引发异常.这可以在更高的水平上捕获,所以我可以优雅地进一步退出.此时,甚至可以根据释放的内存量进行恢复.至少我应该在那一点上希望能够记录一些东西.因此,虽然我已经看到在新的之后检查指针值的代码,但这是不必要的.在C中,您应该检查malloc的返回值.
Bil*_*eal 18
好吧,如果您遇到无法分配内存的情况,那么您将获得std::bad_alloc异常.该异常导致程序堆栈被解除.很可能,应用程序逻辑的内部循环不会处理内存不足的情况,只有更高级别的应用程序应该这样做.因为堆栈正在解开,所以很大一部分内存将被释放 - 实际上应该是程序使用的几乎所有内存.
一个例外是当你要求一个非常大(例如几百MB)的内存块时,这是无法满足的.但是,当发生这种情况时,通常会留下足够小的内存块,这样您就可以优雅地处理故障.
堆栈展开是你的朋友;)
编辑:刚刚意识到问题也被标记为C - 如果是这样的话,那么当发现内存条件不足时,你应该让你的函数手动释放它们的内部结构; 不这样做是内存泄漏.
EDIT2:示例:
#include <iostream>
#include <vector>
void DoStuff()
{
    std::vector<int> data;
    //insert a whole crapload of stuff into data here.
    //Assume std::vector::push_back does the actual throwing
    //i.e. data.resize(SOME_LARGE_VALUE_HERE);
}
int main()
{
    try
    {
        DoStuff();
        return 0;
    }
    catch (const std::bad_alloc& ex)
    {   //Observe that the local variable `data` no longer exists here.
        std::cerr << "Oops. Looks like you need to use a 64 bit system (or "
                     "get a bigger hard disk) for that calculation!";
        return -1;
    }
}
Run Code Online (Sandbox Code Playgroud)
EDIT3:好的,根据评论者的说法,有些系统在这方面没有遵循标准.另一方面,在这样的系统上,无论如何你都将成为SOL,所以我不明白他们为什么值得讨论.但是,如果你是这样的平台上,它是值得牢记.
Ara*_*ion 18
这个问题不会对过度使用的内存做出假设吗?
即,内存不足的情况可能无法恢复!即使您没有剩余内存,malloc在程序尝试使用内存之前,调用和其他分配器仍可能成功.然后,BAM!,一些进程被内核杀死以满足内存负载.
小智 6
我在Linux上没有任何特定的经验,但我花了很多时间在游戏机上进行视频游戏,其中内存耗尽,以及基于Windows的工具.
在现代操作系统上,您最有可能耗尽地址空间.因此,内存耗尽基本上是不可能的.因此,只需在启动时分配一个大缓冲区或缓冲区,以便保存您需要的所有数据,同时为操作系统留下少量数据.将随机垃圾写入这些区域可能是一个好主意,以迫使操作系统实际将内存分配给您的进程.如果你的过程幸存下来,试图使用它所要求的每个字节,那么现在有一些支持保留给所有这些东西,所以现在你是金色的.
写/窃取您自己的内存管理器,并指示它从这些缓冲区分配.然后,在您的应用中始终如一地使用它,或利用gcc的--wrap选项malloc适当地转发来自和朋友的电话.如果您使用任何无法定向的图书馆来打电话给您的记忆管理员,那么他们就会把它们弄得一团糟,因为它们会阻碍您.缺乏可覆盖的内存管理调用是更深层次问题的证据; 如果没有这个特定的组件,你会更好.(注意:即使您正在使用--wrap,相信我,这仍然是一个问题的证据!生命太短暂,无法使用那些不会让您的内存管理过载的库!)
一旦你的内存耗尽,好吧,你已经搞砸了,但是你之前仍然有空闲的空间,所以如果释放你所要求的一些内存太难了你可以(小心)打电话系统调用将消息写入系统日志然后终止,或者其他什么.只要确保避免调用C库,因为他们可能会在你最不期望的时候尝试分配一些内存 - 使用具有虚拟化地址空间的系统的程序员因这种事情而臭名昭着 - 这就是一开始就引起了这个问题的事情.
这种方法听起来像屁股上的痛苦.嗯......是的.但它很简单,值得投入一些努力.我认为有关于此的Kernighan和/或Ritche报价.
如果您的应用程序可能会分配大块内存并面临达到每个进程或 VM 限制的风险,那么等待分配实际上失败是一种很难恢复的情况。到mallocreturnNULL或newthrows 时std::bad_alloc,事情可能已经太远而无法可靠地恢复。根据您的恢复策略,许多操作本身可能仍需要堆分配,因此您必须非常小心可以依赖哪些例程。
您可能希望考虑的另一个策略是查询操作系统并监控可用内存,主动管理您的分配。如果您知道它可能会失败,则可以通过这种方式避免分配大块,从而有更好的恢复机会。
此外,根据您的内存使用模式,使用自定义分配器可能会比标准的内置malloc. 例如,随着时间的推移,某些分配模式实际上会导致内存碎片,因此即使您有空闲内存,堆领域中的可用块也可能没有合适大小的可用块。这方面的一个很好的例子是 Firefox,它切换到dmalloc并看到内存效率有了很大的提高。
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           8356 次  |  
        
|   最近记录:  |