一、概念
主要思想:子程序应该不因传入错误数据而被破坏,哪怕是由其他子程序产生的错误数据。直白些,就是要对传入的数据做有效性校验。
核心思想:要承认程序都会有问题,都要被修改。
二、预防非法输入的数据
什么是好的程序h3>
- 不管输入的数据是什么都不会产生并输出垃圾数据
- 要做到“垃圾进,什么都不输出”、“垃圾进来,出去是错误提示”或“不许垃圾进来”
处理进来垃圾的方法
- 检查子程序所有输入参数的值
- 决定如何处理错误的输入数据
三、断言
什么是断言
- 用于开发和维护阶段
- 只在开发阶段被编译到目标文件中,不编进生成的产品代码中
建立自己的断言机制
C++标准库支持的断言
- C++11之前
函数签名:
作用: 计算表达式 expression,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用abort来终止程序运行。
2. C++11编译期断言static_assert
static_assert是C++11标准引入的一个新关键字,用于在编译期做静态断言。它需要两个参数,第一个是一个可以在编译期返回bool值的常量表达式,第二个是一个字符串常量,用于当断言失败时编译器输出用。
使用断言的建议
1. 用错误处理代码处理预期会发生的状况,用断言来处理绝不应该发生的状况;
2. 避免把需要执行的代码放到断言中;
3. 用断言来注解并验证前条件和后条件;
4. 对于高健壮性的代码,应该先使用断言再处理错误。
四、错误处理技术
用于处理预料中可能要发生的错误
可用的技术手段
- 返回中立值 出现错误数据,可以继续执行,并简单返回一个没有危害的值
- 换用下一个正确的数据
- 返回于前次相同的数据
- 换用最接近的合法值
- 把警告信息记录到日志文件中
- 调用错误处理子程序或对象
- 当错误发生时显示错误信息
- 用最妥当的方式在局部处理错误
- 关闭程序
健壮性和正确性
【正确性】子程序永远不返回不准确的结果。
【健壮性】子程序要不断尝试采取某些措施,以保证软件可以持续地运转下去,哪怕有时会做出一些不够准确的结果。
这两种特性不同软件应用场景,追求不一样。比如,人身安全相关的场景更多的追求正确性。
错误处理需要高层设计
整个程序应该采用一致的方式处理非法参数,确定一种通用的处理错误的方法。
五、异常
概念
- 用异常通知程序的其他部分,发生了不可忽略的错误
- 只有正在例外的情况下才抛出异常
- 不能用异常来推卸责任,能局部处理的错误,就该局部处理掉
- 避免在构造函数和析构函数中抛出异常,除非你在同一地方把它们捕获
- 在恰当的抽象层次抛出异常
- 在异常消息中加入关于导致异常发生的全部信息
- 避免使用空的catch语句
- 了解所有函数库可能抛出的异常
- 考虑创建一个集中的异常 告机制
- 把项目中对异常的使用标准化
- 考虑异常的替代方案
【注】异常会弱化封装性,增加代码复杂度。
六、容损策略之划边界
- 在输入数据时将其转换为恰当的类型
七、辅助调试的代码
不要自动地把产品版的限制强加于开发板之上
应该在开发期间牺牲一些速度和对资源的使用,来换取一些可以更顺畅的内置工具。
尽早引入辅助调试代码
采用进攻式编程
- 何谓进攻式编程r> 在开发阶段让异常显现出来,而在产品代码运行时异常能够自动恢复。
- 使用类似ant和make这样的版本控制工具和make工具
- 编写你自己的预处理器
- 采用mock来模拟外部对象,并把这些保留起来,以便开发和发布来回切换
八、确定在产品代码中该保留多少防御式代码
应该保留的代码的建议
- 保留那些检查重要错误的代码
- 去掉检查细微错误的代码(手段:版本控制、预编译器开关等)
- 去掉可以导致程序硬性崩溃的代码
- 保留可以让程序稳妥地崩溃的代码
- 为你的技术支持人员记录错误信息
- 确认留在代码中的错误信息是友好的
九、你的态度
不要过度防御,防御性代码会带来复杂度,也有可能引入新的bug。
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!