目录
C语言的异常处理方式
基本概念:C 语言中没有专门的异常处理机制,主要使用 返回错误码 和 assert断言
返回错误码:相关变量与函数有errno、perror、sterror
errno
是一个全局变量,用于存储上一个函数调用出错的错误码strerror
是一个函数,它接收errno
的值,返回该错误码对应的错误信息字符串perror
是用于自动打印errno
对应的错误信息的函数,同时还接受一个用户自定义的信息,在打印错误时会将该自定义信息与错误码对应的信息进行拼接,是printf("自定义信息",sterror(errno))的简化版#include <stdio.h> #include <errno.h> #include <string.h> int main() { FILE *file = fopen("nonexistent_file.txt", "r"); if (!file) { // 打印错误码 printf("错误码:%d\n", errno); // 使用 strerror 获取错误信息 printf("错误信息:%s\n", strerror(errno)); // 使用 perror 打印用户信息+错误信息 perror("文件打开失败"); } return 0; }
- 优点:灵活,不会强制程序终止,可以允许程序根据情况选择是否终止或尝试恢复
- 缺点:调用后需要手动检查返回值,不小心忽略时可能导致错误未被处理
assert断言:是一种常见的用于检查异常情况的宏,位于
<assert.h>
assert(expression)
检查表达式expression
是否为true
,若为false
则打印错误信息并终止程序。常用于调试或保证程序关键状态的正确性(如检查指针非空、避免非法内存访问等)#include <stdio.h> #include <stdlib.h> #include <assert.h> #include <errno.h> int divide(int a, int b) { assert(b != 0); // 使用断言处理严重错误 return a / b; } int main() { int result = divide(10, 0); // 断言,直接终止程序 printf("结果是:%d\n", result); return 0; }
- 优点:快速、简单地捕捉严重错误
- 缺点:
assert
会导致程序立即退出,且无法恢复,不适合在产品环境中处理非严重错误
C++的异常处理方式
基本概念:在 C++ 中,异常处理通常使用 try
、throw
和 catch
关键字实现,可以帮助开发者能捕获程序在运行时抛出的异常和并进行处理,而不是使用返回值或错误码来检测错误
- try块:用于包含可能引发异常的代码段
- throw:用于抛出一个匿名的异常对象,
throw
后,程序会停止当前try
块中的执行,并转移到相应的catch
块 - catch块:用于捕获和处理特定类型的异常,
catch
后必须跟一个参数类型,用于指定捕获的异常类型,捕获成功后,可以进行自定义的错误处理方式
#include <iostream>
#include <stdexcept>
void division(double a, double b) {
if (b == 0)
throw std::string("除数不能为零"); // 抛出异常
std::cout << "结果: " << a / b << std::endl;
}
int main() {
try {
division(10, 0); // 可能会抛出异常的代码
}
catch (const std::string& e) { // 捕获 string 类型的异常
std::cerr << "捕获到异常: " << e << std::endl;
}
catch (...) { // 捕获所有异常类型
std::cerr << "捕获到未知异常" << std::endl;
}
return 0;
}
注意事项:
1、不能在try块与catch块间、catch块与catch块间添加代码,一个try块后跟的所有catch块都是用于捕获该try块中throw的异常,且一个try块后必须跟至少一个catch块
try{...}
catch(string& e){...}
catch(...){...}
2、throw的是某个类的匿名对象(也称异常对象)