3

我想编写对内存不足有一定抵抗力的代码。我的尝试是,如果任何内存分配失败,它将暂停执行,并询问操作员是否可以在重新尝试分配之前尝试释放一些内存(或者如果证明不可能,他们可以选择自己终止程序,这取决于他们)

到目前为止,我的代码看起来很丑陋。这是执行任何可能扩展数组的 std::vector 操作的块:

while(pointVector.size() == pointVector.capacity){
    // will not break past this if the while statement remains true
    // ERROR.report() has the power to kill the program if it needs to
    try{
        pointVector.reserve(pointVector.capacity * 2); // edited
    }catch(...){
        ERROR.report(Error::Severity::Memory
                    , __LINE__, __FILE__
                    , "Failed to allocate enough points"
                    , pointVector.size(), 0, 0);
    }
}

pointVector.push_back(point);

ERROR对象专门预先分配了它的所有资源,因此它可以询问操作员而不会引起任何新问题(理论上)。我的问题是,这可以采取更好的形式吗?对于这种情况,C++ 是否有“重试”逻辑?或者这几乎是应该的?

4

5 回答 5

3

通常,不,C++ 没有内置的解决方法。内存不足不是编程语言通常可以容纳的,因此它将失败,假设没有所需的内存就无法继续功能。由于没有内在的“重试”逻辑,所以你会得到类似你所拥有的东西。抱歉,这里没有特别干净的方法。

于 2013-09-16T18:04:42.503 回答
2

除非您有真正的特殊要求,您没有在问题中讨论,否则如果应用程序的内存需求没有得到满足,那么简单地退出并不是不合理的:让用户释放内存并再次运行您的程序。这样可以避免编写在 99.9% 的情况下不需要的额外代码,在这种情况下,这会极大地影响您的性能。

例如,通常以摊销的常数时间运行,但由于容器大小的线性增加push_back,您的“增长 + 后推”组合实际上会以线性时间运行。这种巨大的性能下降将影响您的所有用户,同时只为那些经历内存不足的一小部分用户提供好处。

于 2013-09-16T18:09:52.307 回答
2

根据“你只为你使用的东西付费”的原则,C++ 本身不会“重复”或“重试”。

在这种情况下是否真的值得再试一次,这当然是另一回事......除非你有一个系统正在运行一些系统关键的东西,并且低内存操作是你需要的情况的很大一部分处理,我会说再试一次可能比纾困更糟糕。

您还可以检查错误是否不是std::bad_alloc[或任何“您无法分配”的名称],因为如果有其他错误重试可能毫无意义。

您绝对应该为重复循环的次数设置一个限制(以防万一出现错误ERROR.report())。

[只要您的项目列表相当小,一次增长 32 个就可以了——但我看到的代码几乎与此相同会导致问题,因为一次“仅”增长 32 个到总大小为 32MB,它导致数据被复制无数次,使应用程序看起来像是挂了,因此得到了用户的错误报告。将其更改为几何增长(每次双倍)修复了该特定错误]。

于 2013-09-16T18:05:04.110 回答
1

您正在寻找的功能是std::set_new_handler(new_handler new_p)

它允许您指定一个在分配即将失败时调用的方法,因为您的程序内存不足。然后,此方法有机会释放一些内存,以便分配成功。如果该方法能够释放一些内存,它应该返回 true,否则它必须抛出 bad_alloc 异常或终止程序。(文档set_new_handler有更具体的信息。)

使用的一个很好的特性set_new_handler是,您不必将每个对 new 的调用都包装在 try/catch 块中,以确保您没有耗尽内存。

于 2013-09-16T20:49:25.650 回答
0

我认为您最好的方法是在内存池中分配内存并从那里使用内存,这样您就可以完全控制内存,并且可以在内存不足时进行一些清理,如碎片整理。恕我直言,按照您建议的方式进行恢复只会推迟不可避免的事情。

于 2013-09-16T18:16:40.860 回答