您是否仍然在C ++程序中捕获内存分配失败

时间:2009-03-27 20:49:34

标签: c++ memory-management

我正在为公司写一些指导方针,我需要回答一些棘手的问题。这个很难。

解决方案可以是:

  1. 根本不跟踪。确保使用new分配对象,这将在分配失败时引发异常。该应用程序将死亡,这不是什么大不了的事。 PRO - 代码通常非常干净。

  2. 跟踪内存分配失败并相应地报告,就像任何错误(例如文件访问错误)一样。

  3. 老实说,如果我们使用选项2,我必须编写更多代码。例如,许多std :: tring操作涉及内存分配。如

    std :: string str1,str2; str1 = str2; str + = str2;

    我们的软件将始终运行主要平台,而不是嵌入式平台。不知怎的,我认为选项1是要走的路。你有什么看法?

10 个答案:

答案 0 :(得分:13)

我会捕获内存分配,但只是偶尔。

特别是,我偶尔会将内存分配陷阱:

  • 我知道分配的内存量非常大
  • 如果分配失败,我可以做些什么(例如:优先处理条件并通知用户等)

话虽如此,这两件事情非常罕见 - 通常我最终会让程序死于异常。

答案 1 :(得分:9)

一般情况下,不要检查小额分配的内存分配失败。不可避免地,它比它的价值更麻烦,而且无论如何都很难做到。而且大多数时候你无能为力。在非常大的内存操作上,如果你可以对它做些什么,可能值得根据具体情况考虑事情。

C++ Gotchas: Avoiding Common Problems in Coding and Design 涵盖了这一点。请特别注意 Gotcha #61: Checking for Allocation Failure

  

有些问题应该不是   问,是否有特定的记忆   分配成功是其中之一   它们。

     

[...]错误检查代码就是这样   涉及很少完全正确   最初并且几乎永远不正确   经过一段时间的维护。一个   更好的方法是不要检查   所有:

String **array = new String *[n];
for( String **p = array; p < array+n; ++p )
  *p = new String;
     

此代码更短,更清晰,更快,   并纠正。标准的行为   new是抛出bad_alloc异常   如果分配失败。   这允许我们封装   用于分配的错误处理代码   其余程序失败,   从而使清洁,清洁,和   通常更有效的设计。

答案 2 :(得分:7)

根据另一个建议,我将其作为一个真正的答案。

到目前为止,很多建议基本上已经说过“bad_alloc ==你的程序中的错误”。相反,bad_alloc抛出并不总是表示错误。

作为一个例子,我正在为我正在研究的游戏项目开发一个地图编辑器。有时使用大的地图尺寸会抛出bad_alloc。这并不表示存在错误,只是地图尺寸太大而无法容纳在用户计算机上的可用内存中。这几乎不是我希望程序崩溃的情况,并且在使用'new'运算符创建地图时使用简单的try / catch块可以恢复它。如果失败,简单,我释放剩下的任何记忆并继续随意。并非所有bad_alloc都是直截了当的,所以真正理解为什么抛出bad_alloc很重要。

答案 3 :(得分:5)

除非您正在进行一些非常令人印象深刻的分配,否则您不太可能在32位虚拟内存空间中遇到分配失败。 (在64位系统中更不可能)。如果你的内存耗尽,那么死亡可能会更好。在极少数情况下出现问题并且内存不足时,您无论如何都不可能报告错误。 (当然,除非你在分配失败的情况下事先将内存储备留出来免费。)

一种可能性 - 仅为紧急使用分配大量内存,然后在应用程序中以相当高的级别捕获内存异常,释放紧急内存,记录发生的事情,然后死亡。

答案 4 :(得分:2)

是的,但这取决于您的申请。对于任务关键型应用程序,许多服务器应用程序以及在客户端系统上运行的服务,绝对不应该在OOM情况下崩溃 - 内存条件可能会暂时出现,并且用户希望您的代码在问题清除后继续运行

想象一下,如果一个内存耗尽开始在你的系统上运行,突然你的shell,你的网络浏览器,应用程序等因此而失败。这根本不是一个好的用户体验。

另一方面,如果你的是一个一次性工具,OOM意味着你无法完成用户问你的一件事,那么失败可能就好了。

无论如何,即使对于未处理的情况,您也应该添加一个顶级捕获,可以在OOM实际上由您的代码引起的情况下进行一些日志记录。

答案 5 :(得分:1)

如果你发现内存不足异常,你可以获得发生故障的堆栈跟踪,其中99%的时间是诊断问题所需的全部内容。那就是你的日志。

您可以通过直接使用或释放​​它来锁定1MB缓冲区或可用于生成此信息的内容,以便在创建日志时可以使用内存。

答案 6 :(得分:1)

在现代操作系统上,您的计算机将会冻结,并且可能会在您实际耗尽VM之前很久就会崩溃。这是毫无意义的测试。

答案 7 :(得分:1)

在99.9%的情况下,我的所有C ++应用程序都会因失败的分配而死亡。一旦你内存不足,除非你的应用程序专门用于处理和纠正内存不足的情况,否则你无能为力。

.1%的情况适用于正在进行分配的情况,其中1)已知非常大并且具有显着的失败机会,2)表示适当回退的情况。这是非常罕见,自从我尝试这样的事情以来已经好几年了(我不会再这样做了)。

答案 8 :(得分:0)

分配失败时死亡没什么不对。很可能,之后的其他事情无论如何都会失败。

只是验证你在分配失败时确实得到了一个异常,而不是因为使用了NULL指针。

答案 9 :(得分:0)

我不会检查调用站点,但我建议将大部分程序包装在catch子句中以记录并希望运行错误(内存分配失败可能表示内存泄漏,循环失控,内存不足)管理(分配多个缓冲区但一次只使用一个)等。)