异常,即非预期的情况发生,可能导致程序走向未定义的分支,最严重的造成不可挽回的事故。
我们以模块为单位分析异常的来源和走向:
- 直接调用:模块A调用模块B(一般是底层)的API
需要对B的API进行所有分支进行处理,有些API本身不安全,比如strcpy,可以直接让系统挂掉 - 间接调用:模块A向模块C(一般是上层)注册了一个回调
会向稳定的模块C引入不稳定元素 - 提供调用:模块A向外部提供了接口D
需要向用户提供程序是否执行成功,必要时直接由内部输出错误信息到控制台
对于已经可以捕获的异常,需要通过某种方式记录下来,用来说明不正常的数据(最核心的一点),如终端打印,errno,文件,网络等等。以下是简单的发展轨迹:
- 仅打印到终端和通过返回值告知
- 加入函数名和行号
- 区分消息等级,模块统一
- 区分消息所属channel,通过mask开关
- 加入errno用于告知具体的错误
- 写入文件
参考Linux内核各个等级:
信息等级 | 理解 |
---|---|
KERN_EMERG | 必要资源缺乏,无法工作起来 |
KERN_ALERT | 需要外界参与,比如其他线程,比如直接是用户,提供紧缺资源 |
KERN_CRIT | 在临界区中发现紧急情况,不会用 |
KERN_ERR | 资源出错,正常工作会受到影响 |
KERN_WARNING | 资源受限,还是可以正常工作的 |
KERN_NOTICE | 提示用户一些改进方法等 |
KERN_INFO | 向用户提供当前资源信息 |
KERN_DEBUG | 调试信息 |