异常处理
一般来说,有三种处理错误情况的方法:
- 中止程序
- 返回错误代码
- 抛出异常
要尽量避免第一种方式,第二种和第三种没法说哪一种更高。 C++异常是对程序运行时出现的异常情况的响应。异常提供了一种将控制从程序的一个部分转移到另一个部分的方法
常用异常处理方式try-catch
- https://www.tutorialspoint.com/cplusplus/cpp_exceptions_handling.htm
异常捕获使用准则
- 使用assert处理不应该发生的错误,使用exception处理可能会发生的错误
- 当处理错误的代码通过一个或多个中间函数调用与检测错误的代码分开时,使用异常
- 也可以参考下面的连接:Modern C++ best practices for exceptions and error handling
try-catch 能处理那些异常,以及不能处理那些异常?
-
首先处理的是异常,而不是错误,比如:引用空指针等,无效地址等;该术语优先使用“错误”,因为在某些情况下,异常可能根本不被视为错误在C ++中没有“空指针异常”这样的东西。 您可以捕获的唯一异常是throw表达式显式抛出的异常(另外,正如Pavel所说,标准operator new , dynamic_cast等本质上抛出了一些标准C ++异常)。 C ++中没有其他例外。 取消引用空指针,除以零等不会在C ++中生成异常,它会产生未定义的行为 。 如果您希望在这样的情况下抛出异常,那么您自己有责任手动检测这些条件并明确throw 。 这就是它在C++中的工作方式。
-
连接中列举了可以捕获的c++常见异常常见异常
- std::exception 所有c++标准异常的父类
- std::bad_alloc 可通过 dynamic_cast 被抛出
- std::bad_exception 这是处理 C++ 程序中意外异常的有用设备
- std::bad_typeid 这可以由typeid抛出。
- std::logic_error 理论上可以通过阅读代码检测到的异常
- std::domain_error 这是在使用数学上无效的域时抛出的异常(This is an exception thrown when a mathematically invalid domain is used.)
- std::invalid_argument 这是由于无效参数而引发的
- std::length_error 当创建太大的 std::string 时会抛出此错误
- std::out_of_range 这可以由 ‘at’ 方法抛出,例如 std::vector 和 std::bitset<>::operator
- std::runtime_error 理论上无法通过阅读代码检测到的异常
- std::overflow_error 如果发生数学溢出,则会抛出此错误(This is thrown if a mathematical overflow occurs.)
- std::range_error 当您尝试存储超出范围的值时会发生这种情况
- std::underflow_error 如果发生数学下溢,则会抛出此错误
- 您可以通过继承和覆盖异常类功能来定义自己的异常
- 除此之外的异常需要自己手动添加检测条件并throw
- 其他类似的总结:
- 读取文件,文件不存在
- 被除数等于0
-
也可以参考下面的连接:Modern C++ best practices for exceptions and error handling
-
try-catch不是万能的 try-catch 不能处理哪些问题
- 语法错误
- 异步程序
-
仅用于catch在您知道可以处理错误时指定错误处理操作。如果你自己都不知道如何处理,就不应该使用try-catch。
-
总结,throw-try-out,可以自动处理上述列举的std::exception~std::underflow_error的这些错误,不需要程序员指明,只要在try块中发生这些错误,可以catch到。其他的类型,也可以使用try-catch块使得代码更简洁,但是需要程序员手动做判断异常并通过throw,抛出异常,并由catch捕获
ubuntu系统下 c++ 的异常处理
- 除了一般的try-catch之外,还有linux系统特有的csignal信号捕获方法
异常处理与错误返回码
错误码方法
- 为我们提供了一种简单而可靠的方法来报告各个函数的错误。
异常方法
- 让我们将错误处理代码与正常的控制流分开,并使我们的代码更具可读性。
- 我们可以从多个函数中捕获一个或多个错误,而无需检查每个返回码。
- 让我们在调用堆栈中而不是在确切的故障点处理错误。
- 它比简单的错误代码包含更多信息。
- 异常是在构造函数中报告错误的唯一方法。
- 由于运行时堆栈展开,处理异常的成本很高。
- 未捕获的异常会导致我们的程序中止,从而导致数据丢失。
- 编写异常安全代码很困难,如果没有正确完成,可能会导致资源泄漏。
- 使用异常是一种全有或全无的方法。如果应用程序的任何部分使用异常,那么整个应用程序都应该准备好正确处理异常