我们的程序为什么总是bug不断?

我们的程序通常会出现三个错误: 用户输入错误, 运行期错误以及异常。对于用户输入错误我们会进行很多的合法性检查,一般都是可以避免的,对于运行期错误就比较难办了,我们是最希望把bug在前期的过程的发现,如果需求期的一个bug流入到生产环境中的话那么损失就是无法估量的,客户可能会直接怀疑你家的设计能力。尽管我们都在层层的把关,还是有很多的bug会遗留到生产系统上去。

对运行期错误我们能做的是就是做尽量多的测试(UT/FT/ST 等等),尽可能的去测试各种user case。也做了很多的测试但是线上系统还是有很多处理不完的bug,agile是不是正的适合大型软件的开发,真的是不是每个人都能成为真正的全能手。这章主要是程序的异常处理和断言。怎样让系统检测到异常后进行合理的结束,并不是直接的crash,这里还是有很多的学问, 不同与erlang中的 let it crash, C里面提供了很多的异常处理机制,下面我们就来看看C中有那些合理的处理机制。

第一个就是longjmp和setjmp, 一个结构化的异常处理,setjmp设置一个异常处理点,然后发生异常的时候longjmp到之前set的地方,下面是一个简单的例子,我们检测除法异常如果除数为0我们则jmp到之前set的地方。

#include <setjmp.h>
#include <stdlib.h>
#include <stdio.h>

int div_by_zero_handled = 0;
jmp_buf Div_Failed;

int div(int n, int m) {
  if (m == 0) {
    if (div_by_zero_handled) {
      longjmp(Div_Failed, 1);
    }
  }
  return n / m;
}

int main() {
  div_by_zero_handled = 1;
  if (setjmp(Div_Failed)) {
    printf("can't div by zero \n");
    exit(EXIT_FAILURE);
  }
  
  int n = div(2, 0);
  printf("----->%d\n", n);

  return 0;
}

这里如果在div里面我们检测到除数是0, 那么longjump到之前set的地方, 程序的输出如下:

can't div by zero

下面就来看看在C语言里面这样通过longjmp和setjmp和宏实现一个类似C++ java中 try catch的功能。但这里需要强调一点的是异常处理要尽量的少用,正如书中所讲的一般只在大型应用程序中少量的使用,如果异常越来越多,这通常说明程序有更严重设计问题。

C++/java中的try catch 的语法是这样的:

try 
    S
catch (e1)
    S1
catch (e2)
    S2
catch (en)
    Sn
Else
    So

在e1, e2, en的地方我们通过setjmp创建了异常处理程序,如果S没有触发异常,将跳过程序程序,如果在S执行过程中产生了异常e,并且e是在e1...en之间的一个,那么S的执行被中断,控制立即转给相对应的Except从句总的语句。

最后还是要切记,在代码中异常处理要尽量少用。

-END-


lzh2nix
52 声望19 粉丝

2019年目标: