《C专家编程》学习笔记 (二)C语言特性引发的Bug

C语言的特性引发的BUG:

    分析编程语言缺陷的一种方法就是把所有的缺陷分为3类:不该做的做了,该做的没做,该做的但做得不合适。本文分别用“多做之过”,“少做之过”,“误做之过”代表上述缺陷并加以阐述。

一、多做之过

“多做之过”,就是语言中存在某些不该存在的特性。

  • 由于存在fall through,switch语句会带来麻烦 

    case结构中,default(如果存在)可以出现在case列表里的所有位置,它在其他的case无法匹配时候被选中执行。如果所有case不匹配且没有default,整条switch语句什么都不做。人们希望运行时候给出一个错误信息,提示无匹配。但C语言几乎从来不进行运行时错误检查。因为按照C语言的理念,程序员应该知道自己正在干什么,而且保证自己的所作所为是正确的。

    switch有一个问题:它对case可能出现的值太过于放纵了。例如:可以在switch的左花括号之后声明一些变量,从而进行一些局部存储的分配。

swith另一个问题则是它内部的任何语句都可以加上标签,并在执行时跳到那里,这就有可能破坏程序流的结构化。

switch最大的缺点就是它不会在每个case标签后面的语句执行完毕后自动中止,除非遇到break。如下列代码:

switch(2)
{
  case 1:printf("1\n");
  case 2:printf("2\n");
  case 3:printf("3\n");
  case 4:printf("4\n");
  default:printf("default\n"); 
}

输出结果 将是:

2

3

4

default

这称为“fall through”。即如果case语句后不加break,就依次执行下去以满足某些特殊情况。但是大多数情况下的都是错误的,采用”fall through"的只占了3%。

switch(operator->num_of_oprands)
{
    case 2;process_operand(operator->operand_2);
    /*fall through*/
   case1:process_operand(operator0>operand_1);
   break;
}

由于fall through被广泛认为是一个缺陷,由此甚至出现了一个特殊的注释约定,如上所示。它告诉Lint程序,现在的“fall through”是我们想要的正确的操作。


switch另一个问题:break到底终端了什么

下面代码曾经导致AT&T电话服务全国范围内停顿,时长总共9小时。

network code()
{
    switch (line)
    {
        case THING1;
        doit1();
        break;
        case THING2;
        if (x==STUFF)
        {
            do_first_stuff();
            if (y==OTHER_STUFF)
            {
                break;
            }
            do_later_stuff();
        }
        //代码原意是跳到这里
        initialize_modes_pointer();
        break;
        default:
            processing();
    }//实际上跳到了这里。
    use_modes_pointer();
    //导致modes_pointer未能初始化
}

该代码的作者希望从“if"语句跳出,但他忘了break语句事实上跳出的是最近的那层循环语句或者switch语句。


猜你喜欢

转载自blog.csdn.net/weixin_42197265/article/details/80315080