C++中的异常系统基于try-catch机制和关键字throw。当发生异常情况(例如,资源错误、机制违反)时,在try块内通过throw操作符抛出异常。查找合适的处理程序(catch)的操作是通过展示堆栈直到第一个匹配类型。
重要细节:
std::exception的类)。noexcept说明符。设计:
catch(const std::exception& e)。代码示例:
#include <iostream> #include <stdexcept> void mayFail(bool fail) { if (fail) throw std::runtime_error("进程错误"); } int main() { try { mayFail(true); } catch (const std::exception& ex) { std::cout << "捕获到异常: " << ex.what() << std::endl; } }
如果异常在处理另一个异常时从析构函数中抛出,会发生什么?
答案: 将导致程序通过调用std::terminate()异常终止,因为在处理异常时,不允许生成新的异常(双重异常),否则会破坏堆栈展开。
示例:
struct CrashOnDestruct { ~CrashOnDestruct() noexcept(false) { throw std::runtime_error("析构函数中的错误!"); } }; void func() { CrashOnDestruct obj; throw std::logic_error("错误处理"); } int main() { try { func(); } catch (...) { } } // 将通过std::terminate()终止
故事
在一个大型金融应用程序中,异常是从数据库包装类的析构函数中抛出的。一个主要事务在出现错误时抛出异常,在展开堆栈时调用析构函数,也抛出错误。整个应用程序崩溃,用户工作丢失。开发人员不得不紧急将析构函数中的throw替换为记录日志和正确处理。
故事
一个微服务处理类型为:catch(std::exception)的异常。一个线程抛出了用户自定义类型的异常(未从std::exception继承)。这些错误未被捕获,导致连接意外中断和内存泄漏。
故事
缺少移动容器方法中的noexcept说明符导致标准库使用慢拷贝而不是快速移动操作;性能的显著下降只有在负载测试中被发现。