8.4 运行错误检测和处理 - 编程吧

上一篇 | 下一篇

8.4 运行错误检测和处理

发布: 2007-7-20 13:51 | 作者: 佚名 | 来源: 转载 | 查看: 31次


8.4  运行错误检测和处理
由于WMLScript函数旨在为WAP用户提供各种无线服务,所以它希望用户的浏览器在各种情况下都能够正常工作,因此有效的错误处理能力对它而言是十分重要的。除非万不得已,我们一般情况下不能终止程序的执行,所以即便是WMLScript语言本身没有提供错误处理机制,我们也需要为WMLScript程序运行提供一些工具来处理发生的错误或检查可能导致错误的操作。下面我们就讨论WMLScript程序中可能出现的错误,并给出相应的检测和解决办法。

8.4.1  错误检测
WMLScript的错误检测工具允许我们在程序运行中检测可能出现的错误,不过错误检测工作可能会影响程序的正常运行。由于WMLScript是一种“弱类型”、即对数据类型要求不甚严格的语言,所以数据类型使用不当通常会引起错误。为此,WMLScript专门提供了用于检测无效数据类型的工具,主要包括以下两类:

(1) 检测给定变量的变量值为正确值的函数。这类函数均属于类型有效库函数,如Lang.isInt( )、Lang.isFloat( )、Lang.parseInt( )和Lang.parseFloat( )。这些函数的具体用法我们将在下一章专门讲述。

(2) 检测给定变量的变量值类型为正确类型的操作符。即typeof操作符和isvalid操作符,具体内容我们前面已经讲过(参见7.5.6节),我们这里不再重述。

8.4.2  错误处理的两类情况
由于WAP手机内存有限、外部信号不好或数据运算溢出、下溢等原因,WMLScript程序执行中可能会发生一些不能被错误检测机制所检测、也无法预防的错误。这种错误发生后WMLScript就会尝试着进行错误处理。为了研究与操作上的方便,我们通常把这些错误分成如下两类:

(1) 致命错误。主要指那些能够导致程序中止执行的错误。由于WMLScript的函数通常是在用户端调用,所以致命错误发生时程序会给用户端发出信号,用户端的浏览器就会据此给用户显示出有关错误信息。

(2) 非致命错误。这类错误一般不会导致程序运行中止。错误发生时将向程序返回一个错误值,WMLScript程序将立即寻找相应的处理办法。

有关致命错误和非致命错误的类型及处理方法,我们下面分列两个标题进行介绍。

8.4.3  致命错误及其处理
WMLScript的致命错误主要包括字节码错误、程序异常中止错误、内存耗尽错误和外部异常错误四种情况。虽然说这类错误一旦发生我们无法补救,但了解这类错误的实质有助于我们在程序设计时尽量避免编写这类代码,尽量减少这类错误。

字节码错误
这类错误都与WMLScript的字节码解释器所执行的字节码和指令有关,如内含元素错误、指令非法、指令参数非法,甚至指令无法执行等。

(1) 确认失败。当字节码解释器调用的外部文件无法通过确认有效性检查时,通常会发生确认失败的错误。例如,在下述调用外部文件函数的语句中,如果外部文件的预编译头设置、函数名或参数类型不正确,就都有可能导致确认失败错误:

var a = 3*OtherScript#doThis(param);

这种错误仅当字节码进行确认有效性检查时才能发现,但那时为时已晚,解释器只能中止程序执行,并给用户返回错误信息。

避免这种错误的方法就是程序设计时仔细弄清楚外部文件的位置、函数名称及参数使用方法,正确书写语句代码和定义有关变量,并确保它们有效,而且能通过有效性检查。

(2) 库函数致命错误。每次调用WMLScript的库函数时,如果调用代码不对或函数参数类型不对,都有可能导致库函数致命错误。这会致使库函数调用失败,从而程序中止执行。例如下面这句调用就有可能产生此类错误:

var a = String.format(param);

库函数致命错误发生前无法检测,所以我们程序设计时一定要搞清楚各种库函数的调用方法。

(3) 函数参数无效。如果调用函数时,所用参数类型、数量、参变量值等与函数定义的不能完好匹配,那么就会导致函数参数无效的错误。这种错误也是无法事先检测的,因此程序设计时要正确设置调用函数的各种参数。

(4) 找不到外部函数。如果外部文件没有指定,或者外部文件虽然指定但其中却不含调用的函数,都会导致无法找到外部函数的错误。有关外部文件的预编译设置和外部函数的调用方法,我们上一节已经讲过,只要编程时能够正确地应用那些方法,找不到外部函数的错误还是可以避免的。

(5) 无法加载外部文件。如果网络服务器不存在,或网络服务器故障,或网络通信存在问题,都有可能导致无法加载外部文件的错误,即加载外部文件的指令不能返回结果。这主要是由网络和服务器环境等外在因素引起的错误,程序设计人员通常无能为力,只有通信环境顺畅,才可杜绝此类错误。

(6) 访问受限。如果用户没有权限访问某一外部文件,则当强行访问该外部文件时就会导致访问受限错误,并致使程序执行中止。因此,程序设计中涉及外部文件调用时,一定要根据用户可能的访问权限调用相应的文件。

(7) 堆栈下溢。如果程序代码错误,则每当程序试着取出空堆栈时通常会发生堆栈下溢的错误。这种情况只有在WMLScript字节码解释器生成程序的坏代码时才产生,属于WMLScript解释系统的问题,只有建设好稳定的编译和解释环境,才能避免这类错误。

程序异常中止错误
当WMLScript的函数调用Lang.abort( )库函数时,如果函数调用不匹配,则可能使字节码中止执行,产生程序异常中止错误。例如,下面的语句就有可能导致异常中止错误:

Lang.abort("Unrecoverable error");

避免这类错误的方法是熟悉并正确使用Lang.abort( )库函数。有关该函数的用法我们下一章将专门介绍。

内存耗尽错误
内存耗尽错误与WMLScript解释器的动态操作行为和内存使用方法有关,可能导致堆栈溢出,也可能导致内存不足。

(1) 堆栈溢出。如果程序执行中试着向操作堆栈放入过多的变量,或者试着进行了多层的函数递归调用,那么都有可能导致堆栈溢出。例如,下面这种函数的递归调用就可能会导致堆栈溢出错误,因为它使得变量x的值不断地增加1,直到x值大到用尽内存为止:

function f(x) { f(x+1); };

避免这种错误的方法就是在程序设计时,尽量减少变量数量和递归调用层数,并且杜绝死循环的程序。对于函数的递归调用,我们的建议是最好不采用函数的递归调用,而利用函数嵌套等方法解决。

(2) 内存不足。WMLScript程序执行过程中,如果操作系统不能为解释器分配充足的内存,供程序解释和执行之用,那么就会导致内存不足的致命错误。

例如,下面的函数就可能会导致内存不足:

 

function f(x) {

         x=x+"abcdefghijklmnopqrstuvxyz";

         f(x);

};

 

该程序执行了一个死循环,不断地把“abcdefghijklmnopqrstuvxyz”这个字符串追加到字符串变量x中,直到x的值超过系统内存承受能力而致死机时为止。

一般地,编程中应尽量减小单个数据的规模和内存资源的占用,并避免死循环程序,这样通常能够有效地防止内存不足错误的发生。

外部异常错误
外部异常错误大都是由WMLScript字节码编译器的外部因素引起的,比如用户或系统等因素。

(1) 用户引起的外部异常错误。如果在程序运行中,用户要中止程序的执行并发出了中止指令,比如按了Reset键,那么此时程序就会中止执行,并给用户返回相应的错误信息。

(2) 系统引起的外部异常错误。主要是指由于系统供电不足、断电或设备损坏等因素造成的异常中止程序执行的错误。避免这类错误也没有什么好方法,只有依赖于程序的外部系统环境稳定、可靠,减少意外事件的发生。

8.4.4  非致命错误及其处理
非致命错误主要包括计算错误、常量错误和转换错误等,这些错误不会导致程序崩溃,但会返回一个invalid的无效值或0.0,说明错误性质。

计算错误
计算错误都与WMLScript所支持的数学运算功能有关,比如除数为零、整数溢出、浮点数溢出、浮点数下溢等。

(1) 除数为零。当在程序中出现0除整数、浮点数或其他数据时,都会导致计算错误。例如下面的简单程序就会出现除数为零的计算错误:

 

var a = 10;

var b = 0;

var x = a / b;

var y = a div b;

var z = a % b;

a /= b;

 

避免这种错误的方法并不复杂,只需在程序设计时仔细分析变量数据,尤其是作为除数的变量的值,并通过if条件语句等另外处理这种情况即可。

(2) 整数溢出。程序中执行整数操作时有可能会出现整数计算结果溢出的错误。这种错误通常是整数经计算后产生的,所以编程阶段一般难以发现。不过在程序调试阶段,我们可以通过不断测试比较大的整数运算,来检测是否会出现整数溢出的错误。如果出现,就要对程序中的整数运算做适当的调整,以避开整数无限增大的情况。

例如,下面对WMLScript所能接受的最大整数的求和运算就会导致整数溢出的错误:

 

var a = Lang.maxInt();

var b = Lang.maxInt();

var c = a + b;

 

(3) 浮点数溢出。与整数溢出一样,程序中执行浮点数操作时有可能会出现浮点数计算结果溢出的错误。例如,下面对两个极大浮点数的求积运算就会导致浮点数溢出的错误:

 

var a = 1.6e308;                     // 1.6e308 = 1.6×10308,这是非常大的数!

var b = 1.6e308;

var c = a * b;

 

这种错误一般也是在浮点数计算后产生的,编程阶段很难发现。所以在程序调试阶段,我们需要通过不断测试较大浮点数的运算,来检测是否会出现此类溢出错误。如是,则调整程序,避免这类溢出错误。

(4) 浮点数下溢。当程序中对非常小的浮点数进行操作时,就有可能导致浮点数下溢的错误。这种错误通常也是经计算后产

此新闻共有2页 1 2

字号: | 推荐给好友

 

评分:0

我来说两句

seccode