我正在为公司写一些指导方针,我需要回答一些棘手的问题。这个很难。
解决方案可以是:
根本不跟踪。确保使用new分配对象,这将在分配失败时引发异常。该应用程序将死亡,这不是什么大不了的事。 PRO - 代码通常非常干净。
跟踪内存分配失败并相应地报告,就像任何错误(例如文件访问错误)一样。
老实说,如果我们使用选项2,我必须编写更多代码。例如,许多std :: tring操作涉及内存分配。如
std :: string str1,str2; str1 = str2; str + = str2;
我们的软件将始终运行主要平台,而不是嵌入式平台。不知怎的,我认为选项1是要走的路。你有什么看法?
答案 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子句中以记录并希望运行错误(内存分配失败可能表示内存泄漏,循环失控,内存不足)管理(分配多个缓冲区但一次只使用一个)等。)