3.3.1 数据引用错误
1.是否有引用的变量未赋值或未初始化?这可能是最常见的编程错误,在各种环境中都可能发生。在引用每个数据项(如变量、数组元素、结构中的域)时,应试图非正式地“证明”该数据项在当前位置具有确定的值。
2.对于所有的数组引用,是否每一个下标的值都在相应维规定的界限之内?
3.对于所有的数组引用,是否每一个下标的值都是整数?虽然在某些语言中这不是错误,但这样做是危险的。
4.对于所有的通过指针或引用变量的引用,当前引用的内存单元是否分配?这就是所谓的“虚调用”(dangling reference)错误。当指针的生命期大于所引用内存单元的生命期时,错误就会发生。当指针引用了过程中的一个局部变量,而指针的值又被赋给一个输出参数或一个全局变量,过程返回(释放了引用的内存单元)结束,尔后程序试图使用指针的值时,这种错误就会发生。与前面检查错误的方法类似,应试图非正式地“证明”,对于每个使用指针值的引用,引用的内存单元都存在。
5.如果一个内存区域具有不同属性的别名,当通过别名进行引用时,内存区域中的数据值是否具有正确的属性?在FORTRAN语言中对EQUIVALENCE语句使用,或COBOL语言中对REDEFINES语句使用的地方,都可能发生这种错误。例如,一个FORTRAN语言程序包含一个实型变量A和一个整型变量B,两者都通过使用EQUIVALENCE语句而成为同一内存区域的别名。如果程序先对A赋值,然后又引用变量B,由于机器可能会将内存中用浮点位表示的实数当做整数,在这种情况下错误就可能发生。
6.变量值的类型或属性是否与编译器所预期的一致?当C、C++或COBOL程序将某个记录读到内存中,并使用一个结构来引用它时,由于记录的物理表示与结构定义存在差异,这种情况下错误就可能发生。
COBOL与Fortran背景资料
COBOL和Fortran是两门分别面向商业处理和科学计算开发方向的元老级别的编程语言,这两门语言为数代的程序员提高开发效率作出了不可估量的贡献。
COBOL(取自COmmon Business Oriented Language的粗体部分)的雏形诞生于1959年前后,其设计的主要目的是为了支撑大型机系统上的商业应用软件的开发工作,其最初的规格设计可谓是集众家之长,当时参与COBOL项目的有知名的计算机制造商以及联邦政府机关,他们共同创造了一门全新的、面向商业的、能够运行在各种硬件和操作系统之上的编程语言。
这些年来,COBOL语言标准不断完善和发展。到2002年,COBOL几乎能够在大多数的操作系统平台进行开发和运行,甚至还推出了一个用来集成.NET开发环境的面向对象版本。
到本书写作之际,目前最新版本的COBOL是Visual COBOL 2010。
Fortran(最早拼写成FORTRAN,不过现在更倾向于首字母大写的规范)的诞生比COBOL还要稍微早点,其规格定义最早可以追溯到20世纪50年代早中期。和COBOL类似,Fortran被设计用来针对某些特殊类型(尤其是科学和数字计算方面)的大型机应用系统开发。Fortran这个名字来源于当时IBM一个叫做Mathematical FORmula TRANslating System(名字取自字体加粗部分)的系统。虽然最初的Fortran只有32种语句,但是这已经远远超越了当时的汇编程序设计语言,是具有划时代意义的进步。
到本书出版之际,最新的Fortran版本是Fortran 2008,已经在2010年被标准委员会正式通过。和COBOL一样,Fortran语言的演进伴随着对更多硬件和操作系统的支持,不过有一点不同的是,不管是现有系统的开发还是老系统的维护,Fortran都可能比COBOL应用得更广泛。
7.在使用的计算机上,当内存分配的单元小于内存可寻址的单元大小时,是否存在直接或间接的寻址错误?例如,在某些条件下,定长的位串不必以字节边界为起点,但是地址又总是指向字节边界的。如果程序计算一个位串的地址,稍后又通过该地址引用这个位串,可能会指向错误的内存位置。将一个位串参数传送给一个子程序时,也可能发生这种情况。
8.当使用指针或引用变量时,被引用的内存的属性是否与编译器所预期的一致?这种错误的一个例子是,当一个指向某个数据结构的C++指针,被赋值为另外的数据结构的地址。
9.假如一个数据结构在多个过程或子程序中被引用,那么每个过程或子程序对该结构的定义是否都相同?
10.如果字符串有索引,当对数组进行索引操作或下标引用,字符串的边界取值是否有“仅差一个”(off-by-one)的错误?
11.对于面向对象的语言,是否所有的继承需求都在实现类中得到了满足?