9

我正在重构旧代码,我想解决的一件事是处理错误的方式。我很清楚异常以及它们是如何工作的,但我不完全确定它们是我试图处理的情况的最佳解决方案。

在这段代码中,如果事情没有得到验证,那么展开堆栈真的没有理由或优势。我们完成了。试图挽救这艘船毫无意义,因为它是通过 Sun Grid Engine 并行运行的非交互式代码。用户无法干预。更重要的是,这些验证失败并不真正代表特殊情况。他们是意料之中的。

那么我该如何最好地处理这个问题呢?我不确定我想要的一件事是每个可能失败的类方法中的退出点。这似乎是不可维护的。我错了吗?在这样的代码中调用exit()abort()在故障点是否可以接受?或者我应该一直抛出异常回到main中的一些通用catch语句?有什么好处?

4

4 回答 4

4

如果程序不能优雅地处理错误,终止程序是可以接受的。您可以做的事情很少:

  • abort()如果您需要核心转储,请致电。
  • exit()如果您想有机会运行那些注册的例程atexit()(最有可能调用全局 C++ 对象的析构函数),请调用。
  • 调用_exit()以立即终止进程。

只要你明白自己在做什么,知道你的其他选择,并且心甘情愿地选择那条路,使用这些功能并没有错。毕竟,这就是存在这些功能的原因。因此,如果您认为尝试处理错误或在错误发生时执行其他任何操作没有任何意义 - 请继续。我可能会尝试记录一些信息性消息(例如,到 syslog),然后调用_exit. 如果日志记录失败 - 调用abort以获取沿终止的核心。

于 2012-05-21T14:31:17.567 回答
4

抛出要在 main 中捕获的异常然后退出意味着您的 RAII 资源对象被清理。在大多数系统上,很多资源类型都不需要这样做。操作系统将清理内存、文件句柄等(尽管我使用的系统未能释放内存意味着它一直分配到系统重新启动,因此在程序退出时泄漏不是一个好主意。)

但是还有其他资源类型您可能想要干净地释放,例如网络或数据库连接,或者您正在驾驶并需要安全关闭的机械设备。如果一个应用程序使用了很多这样的东西,那么你可能更愿意抛出一个异常来将堆栈展开回 main,然后退出。

所以适当的退出方法取决于应用程序。如果应用程序知道它是安全的,那么调用 _Exit()、abort()、exit() 或 quickexit() 可能是完全合理的。(库代码不应该调用这些,因为显然库不知道它对于每个将使用该库的应用程序是否安全。)如果在应用程序退出之前必须执行一些关键的清理,但你知道它是有限的,然后应用程序可以通过 atexit() 或 at_quick_exit() 注册该清理代码。

所以基本上决定你需要清理什么,记录它,实施它,并尝试确保它已经过测试。

于 2012-05-21T14:59:59.143 回答
2

我建议调用全局函数

void stopProgram() {
  exit(1);
}

稍后您可以更改它的行为,因此它是可维护的。

于 2012-05-21T14:21:15.980 回答
1

正如您所指出的,在整个代码中使用exitorabort是不可维护的……此外,将来可能会有一种机制可以让您从错误中恢复,或者以比简单的更优雅的方式处理错误退出,并且如果您已经在其中硬编码了此功能,那么将很难撤消。

抛出一个被捕获的异常main()是你目前最好的选择,如果你在不同的场景下运行代码,这也将为你提供灵活性,这将允许你从错误中恢复,或者以不同的方式处理它们。此外,如果您决定添加更多调试支持等,抛出异常可能会有所帮助,因为在您决定让程序退出之前,它将为您提供实现日志功能并从软件中的隔离和可维护点记录程序状态的位置。

于 2012-05-21T14:24:34.500 回答