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