terminate
从理论上讲,如果您同时有两个未处理的异常,您就有可能拥有您的程序。然而,这是一种相当罕见的情况。
- 在准备异常期间抛出:很好(尽管您不会得到预期的异常)
- 在异常复制期间抛出(通常被忽略,可避免):崩溃
- 放卷时投掷:crash
- 处理异常时抛出(
catch
):很好(毕竟重新抛出不同的异常是很常见的)
因此,这里可避免的风险是,如果您的异常的复制构造函数可能碰巧抛出。通过将状态移到shared_ptr
异常中包含的状态来逃避问题是微不足道的。它使副本有点“特殊”(因为它们与原件共享它们的状态),但如果它被正确记录,它不应该引起任何悲伤。
更大的风险是在堆栈展开期间。但是,它仅在析构函数抛出时才会发生。
就个人而言,我使用的例外包括:
- 一个错误代码(为了让 API 正确显示/编码,所有错误消息都映射到一个代码,它对中文/韩文/日文有帮助,真的)
- 一条日志消息,带有一些详细信息(导致问题的项目的 ID/名称,翻译另一个异常时的原始错误,有什么帮助!)
- 抛出异常的函数/文件/行
- 抛出异常的时间
- 附加说明(在堆栈展开期间“即时”附加)
- 完整的回溯(使用 Linux 特定功能)
这里唯一有争议的一点是on the fly bit,因为它可能会有效地崩溃。另一方面,我在服务器上工作,因此很容易(并且紧急)修复崩溃,并且在过去的 5 年中,我非常小心,没有导致崩溃(这种方式;))。
请注意,此方案显然仅在您很少使用异常时才可用。如果您经常为每个任务抛出十几个异常,那么性能可能会令人无法接受。另一方面,主要编译器使用的零成本模型已经严厉惩罚了异常路径,所以......