12

所以我在开发中经常使用 Qt 并且喜欢它。Qt 对象的通常设计模式是使用new.

几乎所有示例(尤其是 Qt 设计器生成的代码)都绝对不检查std::bad_alloc异常。由于分配的对象(通常是小部件等)很小,这几乎不是问题。毕竟,如果您未能分配 20 个字节之类的东西,那么您可能无法解决这个问题。

目前,我采用了在 try/catch 中包装“大”(大小超过一页或两页的任何内容)分配的策略。如果失败,我会向用户显示一条消息,几乎任何更小的消息,我都会让应用程序崩溃并出现std::bad_alloc异常。

所以,我想知道这方面的思想流派是什么?

检查每项new操作是否是好政策?还是只有我认为有可能失败的人?

此外,在处理资源可能受到更多限制的嵌入式环境时,这显然是一个完全不同的故事。我在桌面应用程序的上下文中询问,但也会对涉及其他场景的答案感兴趣。

4

6 回答 6

17

问题不在于“在哪里捕捉”,而是“捕捉到异常时该怎么做”。

如果你想检查,而不是包装try catch你最好使用

    #include <new>
    x = new (std::nothrow) X();
    if (x == NULL) {
        // allocation failed
    }

我通常的做法是

  • 在非交互式程序中,在主级别捕获并在那里显示适当的错误消息。

  • 在具有用户交互循环的程序中,也要在循环中捕获,以便用户可以关闭一些东西并尝试继续。

例外地,还有其他地方的捕获是有意义的,但很少见。

于 2009-08-20T18:49:03.320 回答
11

尽可能处理异常。如果分配失败,并且您的应用程序在没有那部分内存的情况下无法继续运行,那么为什么还要检查错误呢?

在可以处理的情况下处理错误,当有一种有意义的方法可以恢复时。如果您对错误无能为力,就让它传播。

于 2009-08-20T19:03:27.847 回答
6

我通常在用户启动操作时捕获异常。对于控制台应用程序,这意味着在 中main,对于 GUI 应用程序,我将处理程序放在按钮单击处理程序等位置。

我认为在操作中间捕获异常没有什么意义,用户通常期望操作成功或完全失败。

于 2009-08-20T18:52:33.750 回答
4

这是一个相对较旧的线程,但是当我在 2012 年在这里进行新/删除覆盖时搜索“std::bad_alloc”注意事项时确实出现了。

我不会把“哦,无论如何你都无能为力”的概念作为一个可行的选择。我个人在自己的分配中使用上面提到的“if(alloc()){} else { error/handling }”方式。通过这种方式,我可以正确处理和,或者,在各自有意义的上下文中报告每个案例。

现在,其他一些可能的解决方案是: 1)覆盖应用程序的新/删除,您可以在其中添加自己的内存不足处理。

尽管与其他海报状态一样,特别是在不了解特定上下文的情况下,主要选择可能只是关闭应用程序。如果是这种情况,您将希望您的处理程序预先分配它所需的内存,或者,使用静态内存,因此希望它自己的处理程序不会耗尽。

在这里,您至少可能会弹出一个对话框,并在以下行中说:“应用程序内存不足。这是一个致命错误,现在必须自行终止。应用程序必须在最低系统内存要求下运行。发送调试报告到 xxxx”。处理程序还可以保存任何正在进行的工作等,以适应应用程序。

无论如何,您都不希望将其用于关键的事情,例如(警告,业余幽默):航天飞机,心率监测器,肾透析机等。当然,这些事情需要更强大的解决方案,使用故障保险柜、紧急垃圾收集方法、100% 测试/调试/模糊测试等。

2) 与第一个类似,使用您自己的处理程序设置全局“set_new_handler()”,以在全局范围内捕获内存不足的情况。至少可以处理#1中提到的事情。

于 2012-01-03T23:35:21.577 回答
1

真正的问题是您是否应该捕获 std::bad_alloc 异常?在大多数情况下,如果您的内存不足,那么您无论如何都注定要失败,并且可能会考虑结束您的程序。

于 2012-08-08T11:09:12.927 回答
0

处理它main()(或 Qt 中等效的顶级异常处理程序)

原因是 std::bad_alloc 要么在您耗尽内存空间(32 位系统上为 2 或 3 GB,在 64 位系统上不会发生)时发生,要么在您耗尽交换空间时发生。现代堆分配器未调整为从交换空间运行,因此这将是一个缓慢而嘈杂的死亡 - 您的用户可能会提前杀死您的应用程序,因为它的 UI 不再响应。在 Linux 上,默认情况下操作系统的内存处理非常糟糕,以至于您的应用程序很可能会被自动终止。

所以,你能做的很少。承认你有一个错误,看看你是否可以保存用户可能已经完成的任何工作。为了能够做到这一点,最好尽可能中止。是的,这实际上可能会丢失一些最后的用户输入。但正是这一行为可能引发了 OOM 情况。目标是保存您可以信任的任何数据。

于 2009-08-21T08:05:36.740 回答