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语句。