错误处理在编程中是很重要的,可以在调试,发布的时候少了很多麻烦,以往在做软件的时候总是少了错误处理,导致用户用来莫名其妙,在查找问题的时候也是没有头绪
最近在总结一些错误处理技巧,总共有这么一些方法:
1.LOG
log在关键的时刻可以救命的东西,因此我一直提议组里的人多使用log,但是log记多了也不好,会导致混杂信息太多
之前公司里面有个3D的写log太频繁,结果导致运行8小时就写了4G的log导致运行崩溃,当时给他找了好多天才发现是log的问题
先阶段来说,我们的log主要是用在处理输入输出上面,因此我建议在以下几个地方记录log:
1.1 与外部库最近交互的地方
这里的外部库就是非本公司所使用的开发库,比如我们公司使用的BOOST, QT这些库
1.2. IO输入输出的数据
主要是网络,文件,串口这些信息,记录信息的时候除了有一份二进制的原始数据以外,最好还附带一份可视化的数据
1.3. 逻辑处理的地方
这个就比较难以界定了,其实到现在我没法很好地记录这方面的数据,但是我的建议是,如果这个逻辑处理是和外部交互的,比如网络,串口,一定要把这个逻辑给记录下来
2.错误值返回
错误值返回是比较古老的方式,好处程序是按照流程来处理的,坏处就是在if内嵌if的时候代码看起来会很杂乱,不过有do..while(false)这个技巧可以避免
3.异常处理
异常处理在C++里面是比较争议的一种方式,最近在项目里面我也开始使用异常处理,所以感慨比较多,但是给我的感觉就是这个不是用在错误处理的,之前看C++之父写的那本书的时候,他也提到过这一点,他是在处理异常而不是来处理错误的,很多C++的书都告诉用户异常处理是代替C语言方式的返回值的,但是C++之父强调了两点:
1.异常处理是用来处理异常的,这些异常需要是可恢复的
2.异常处理是用来解决构造函数无法报告错误的
但是怎么界定错误和异常这个我到现在还是没法好好地界定
之前书上很多都也都不建议使用异常,因为C++里面没有GC,但是我们可以使用RAII以及BOOST_EXIT和shared_ptr(其实也是RAII)来解决问题
因为好像在现代C++里面,好像没什么理由再不使用异常了
在之前用python的时候,python大部分都是利用异常来处理错误,python使用异常处理,我一直觉得这种方法不错,但是python本身的异常类型也有点多,如果要在C++里面模仿这种方法,我们必须要定义很多异常类型,否则无法把足够的异常信息带给外部,但是这样会造成的文件依赖
比如最近我在写一个函数,这个需要将一个格式的文件转换成对应的数据存储到SQL里面,需要做如下动作:
在每一个动作的时候,如果发生错误,我们都需要报告给外部知道发生了什么错误,以便于用户去处理
1.读取源文件
1.1 文件不存在
2.读取对应的数据
1.1 文件格式错误,或者缺少数据
3.根据对应的数据去读取对应的图片
1.1 图片不存在,或者图片格式错误
4.创建对应的sql文件
1.1 sql文件本身已经存在,需要询问用户究竟是代替掉还是取消这个行为??
5.创建对应的表
1.1 创建表错误
6.将对应的数据存储到sql文件
1.1 执行一些sql语句发生错误,或者读取对应的图片的时候发生错误,询问用户是要无视这个错误还是要继续执行
如果在函数内发生错误将会有如下的处理方式:
1.直接返回false,这种类型是无法继续执行的 (1,2,5)
2.需要询问用户是否继续执行(3,4)
最早的第一个版本我是使用异常的,但是后来发现,无法去询问用户是否继续执行
然后我改用bool,无法让外部知道是哪一步出错了,如果要让用户知道哪一步错误,需要定义一堆的enum,而且也无法让外部去询问
最后我的解决方案是:
把每一个动作封装成一个函数,然后在UI层分成每一步执行,这样可以达到上面的效果,但是无法将动作封装成一个函数
4.coroutine
这个是那天晚上想到的,是为了解决要寻外上面的例子里面需要询问外部的,在执行函数的时候传入一个coroutine,这样如果发生错误则暂停执行,返回到外部,由外部来决定是否继续执行