7.1.2 语义或“运行期”错误 语法错误的发现和处理是令人烦恼的,但在编程中会遇到一些真正“令人兴奋”的另一类型的错误——语义错误(semantic error)或称“运行期”错误(runtime error)。这类错误仅当运行一个脚本代码或其他程序时才会发现。换句话说完整有效的代码已经通过解释器或编译器的解释或编译,在执行时产生了错误。术语“运行期错误”通过是指语义错误的结果,也就是说这类错误存在于代码的语义中,当代码运行时它们才变成可见的。 这种区别来自于这种事实:程序编译器或解释器在处理程序代码之前必须建立一种内部代码的描述,涉及多种结构开头和结尾的匹配,以便标明每种结构包含什么内容,然后分析每个句子,以便知道如何执行这个句子。例如,如果在程序代码中有一个If Then … Else … End If 结构,解释器或编译器做的第一步工作就是分析哪些语句在“Then”的部分,哪些在“Else”部分。这一步的目的是,在对结构中的If条件进行测试之后,可以决定该到哪个分支去执行。 编译器(诸如在编程语言像Visual Basic和C++中见到的那种)和解释器(诸如用于像VBScript和JScript那样的脚本语言的解释器)之间真正区别在于:编译器不试图运行程序代码,而是在对源程序进行两次预处理后,形成二进制指令或符号代码,并形成一个.exe文件或.dll文件。解释器不含有代码的文件,而是在运行时逐步执行。 1. 使运行停止的错误 如果程序中含有一个语义错误,通常在运行时可得到提示。如果幸运的话,当错误发生时,程序会停止,这样可以容易地找出错误所在。例如,下面这段程序定义了一个有六个元素的数组。 <% Dim arrValues(5) 'to hold six elements, indexed from 0 to 5 ArrValues(6) = "Whoops, got an error" %> 如果试图读或设置下标为6的元素值,可以得到一个运行期错误,如图7-7所示:
图7-7 程序执行结果6 注意这里的错误类型是“runtime”(相当于语义)错误,而不是语法错误。错误信息显示了错误所在行数和错误的描述,有助于我们比较容易地找到相应的错误。但这是一个简单的例子,在更复杂的程序代码中,这种错误可能出现在一些遍历一些值并把它们加到一个数组中程序中。如下所示: <% Dim arrValues(5) ' to hold six elements For intLoop = 0 To intListCount ' the number of items in some list arrValues(intLoop) = Request.Form("SelectedItems")(intListCount) Next %> 这种情况下,很可能是得到了过多的列表条目,或者是数组的索引不够,根据代码的要求,可以判断是那种错误,并且能够通过增加数组大小来解决这个错误。 <% Dim arrValues(10) ' to hold eleven elements For intLoop = 0 To intListCount ' the number of items int some list arrValues(intLoop) = Request.Form("SelectedItems")(intListCount) Next %> 或者相应地设置循环的参数来解决处理这个错误。 <% Dim arrValues(5) ' to hold six elements IntArrayMax = intListCount If intArrayMax > 5 Then intArrayMax = 5 For intLoop = 0 To intArrayMax ' only add the first six items arrValues(intLoop) = Request.Form("SelectedItems")(intListCount) Next %> 许多其他运行期错误能够使网页运行停止,诸如一些组件或对象的实例化失败,原因是有ProgID错误,或者是因为组件没有正确安装。在这些情况下,结果总是给出“ActiveX Cannot Create Object”错误提示信息,后面跟着调用Server.CreateObject方法的行号。 2. 产生错误结果的错误 上面提到,如果遇到一个使程序代码停止的运行期错误,我们可能是幸运的。但是另一种情况是程序能很好地执行,好像什么也没有发生,最后产生一个错误的结果。这是最难发现和解决的错误,因为意识不到哪里出错了。例如,假设有一个网页,这个网页把用户的生日作为日期型的值,并且单独显示日期元素(可以把它们作为三个条目加到一个数据库中)。 <% ' get the value from the Request and display it datBirthdate = Request.Form("Birthdate") Response.Write "The value you entered is: " & datBirthdate & "<P>"
' get the individual date elements intDay = Day(datBirthdate) intMonth = Month(datBirthdate) intYear = Year(datBirthdate)
图7-9 错误提示屏幕 (1) 如果不是一位JScript专家 在寻找错误时,这不是一个大问题,因为我们能够迅速发现为什么会出现错误。事实上网页停止运行有助于我们跟踪错误。然而意外的错误可能会发生。例如,用JScript重写程序代码,由于不是一位JScript专家,里面出现一些细小错误。 <% // get the value from the Request and display it var datBirthdate = new Date(Request.Form("Birthdate")); Response.Write("The value you entered is: " + datBirthdate + "<P>");
// get the individual date elements intDay = datBirthdate.getDay(); intMonth = datBirthdate.getMonth(); intYear = datBirthdate.getYear();