C++ 什么';这是在C/C++;?

C++ 什么';这是在C/C++;?,c++,c,linux,C++,C,Linux,我正在编写一个缓存应用程序,它会消耗大量内存 希望我能很好地管理我的记忆,但我在想什么呢 如果我的内存用完了该怎么办 如果分配一个简单对象的调用失败,那么即使是syslog调用也可能失败吗 也会失败吗 编辑:好的,也许我应该澄清这个问题。如果malloc或new返回NULL或0L值,则本质上意味着调用失败,并且由于某种原因无法提供内存。那么,在这种情况下,明智的做法是什么 EDIT2:我刚刚意识到,对“new”的调用可能引发异常。这可以在更高的层次上被捕捉到,这样我也许可以优雅地离开更高的层次。

我正在编写一个缓存应用程序,它会消耗大量内存

希望我能很好地管理我的记忆,但我在想什么呢 如果我的内存用完了该怎么办

如果分配一个简单对象的调用失败,那么即使是syslog调用也可能失败吗 也会失败吗

编辑:好的,也许我应该澄清这个问题。如果malloc或new返回NULL或0L值,则本质上意味着调用失败,并且由于某种原因无法提供内存。那么,在这种情况下,明智的做法是什么


EDIT2:我刚刚意识到,对“new”的调用可能引发异常。这可以在更高的层次上被捕捉到,这样我也许可以优雅地离开更高的层次。在这一点上,甚至可以根据释放的内存量进行恢复。至少到那时我应该能够记录一些东西。因此,虽然我见过在new之后检查指针值的代码,但这是不必要的。在C语言中,您应该检查malloc的返回值。

如果在分配内存失败的情况下,您将得到一个
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;
    }
}
#包括
#包括
void DoStuff()
{
std::矢量数据;
//在这里的数据中插入一大堆东西。
//假设std::vector::push_back执行实际抛出
//i、 e.数据。调整大小(此处的一些值较大);
}
int main()
{
尝试
{
DoStuff();
返回0;
}
捕获(常数标准::错误分配和释放)
{//注意,局部变量'data'在这里不再存在。

std::cerr我在Linux上没有任何具体的经验,但我花了很多时间在游戏机上玩视频游戏,在游戏机上内存不足是不可能的,在基于Windows的工具上也是如此

在现代操作系统上,您最有可能耗尽地址空间。因此,耗尽内存基本上是不可能的。因此,只要在启动时分配一个或多个大缓冲区,以便保存您所需的所有数据,同时为操作系统保留少量数据。将随机垃圾写入这些区域可能是一个好主意,以便强制操作系统将内存分配给你的进程。如果你的进程成功地使用了它要求的每一个字节,那么现在所有这些东西都有了某种支持,所以现在你是黄金

编写/窃取您自己的内存管理器,并引导它从这些缓冲区进行分配。然后在应用程序中始终如一地使用它,或利用gcc的
--wrap
选项适当地转发来自
malloc
和朋友的呼叫。如果您使用任何无法被引导调用到内存管理器的库,请将它们丢弃,因为缺少可重写的内存管理调用是深层次问题的证据;如果没有这个特定组件,你会更好。(注意:即使您正在使用
--wrap
,相信我,这仍然是一个问题的证据!生命太短暂,无法使用那些不会让您超载其内存管理的库!)

一旦你的内存用完,好吧,你就完蛋了,但你仍然有你以前留下的空闲空间,所以如果释放一些你要求的内存太难,你可以(小心地)调用系统调用,将消息写入系统日志,然后终止,或者其他任何操作。只需确保避免调用C库,因为它们可能会在您最不希望的时候尝试分配一些内存—使用具有虚拟化地址空间的系统的程序员在这类事情上臭名昭著—而这正是问题所在首先导致问题的东西


这种方法听起来像是一种痛苦。嗯……的确如此。但它很简单,值得为此付出一点努力。我认为关于这一点有一句克尼汉和/或里切的名言。

这个问题不是对过度投入的记忆做出了假设吗


也就是说,内存不足的情况可能无法恢复!即使您没有剩余内存,在程序尝试使用内存之前,对
malloc
和其他分配器的调用可能仍然会成功。然后,BAM!,一些进程被内核终止,以满足内存负载。

如果您的应用程序可能会分配较大的bl内存不足并有可能达到每个进程或VM限制,等待分配实际失败是一种很难恢复的情况。当
malloc
返回
NULL
new
抛出
std::bad_alloc
时,可能无法可靠恢复。取决于您的恢复策略当然,许多操作本身可能仍然需要堆分配,因此您必须非常小心可以依赖哪些例程

您可能希望考虑的另一个策略是查询OS并监视可用的MEM。