ASP 3.0高级编程(三十一)
程序员文章站
2022-05-23 08:57:36
7.1.2 语义或“运行期”错误
语法错误的发现和处理是令人烦恼的,但在中会遇到一些真正“令人...
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 inpidual date elements
intday = day(datbirthdate)
intmonth = month(datbirthdate)
intyear = year(datbirthdate)
and display them
response.write "day: " & cstr(intday) & "<br>"
response.write "month: " & cstr(intmonth) & "<br>"
response.write "year: " & cstr(intyear) & "<br>"
%>
图7-8是结果,是用美国日期风格月/日/年显示的,好像一切都没有问题。
图7-8 显示生日的屏幕
然而如果输入一个非法日期,或者让输入文本框空着,便得到一个运行期错误,如图7-9所示:
图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 inpidual date elements
intday = datbirthdate.getday();
intmonth = datbirthdate.getmonth();
intyear = datbirthdate.getyear();
// and display them
response.write("day: " + intday.tostring() + "<br>");
response.write("month: " + intmonth.tostring() + "<br>");
response.write("year: " + intyear.tostring() + "<br>");
%>
图7-10即是运行结果,尽管程序没有停止运行并给出运行期错误,还是马上看出其中有些问题,月份不可能是0。
图7-10 显示生日的屏幕
问题出现的原因在于jscript的getmonth函数返回的结果为0~11范围内的数,因此需要再加1,才能得到正确的结果。
intmonth = datbirthdate.getmonth() + 1;
(2) 衍生错误
即使不把初始值赋给网页去和结果比较,上面这种错误也可能是相当明显的。然而,如果面对的是一个数据库,并且没有看到显示出不正确的结果,可能不知道为什么程序不能正确地更新数据库。更糟糕的是,如果简单地把数值做为整型数据存入数据库,可能直到有人试图对这个数据查询时才能发现这个错误。
现在,发现大约有十二分之一的成员出生在0月份可能会使人吃惊,并会引起一些问题。记住,不仅仅是那些1月份出生的人员存在数据库中的信息不正确,而且每个成员都是这样。如果有许多应用程序都能增加和修改这个数据库中的记录,跟踪这个错误可能是艰苦的工作,特别是,不能去查找错误出现在哪个程序行,而是首先要找出错误出现在哪个应用程序中。
(3) 掌握日期的用法
在上面的程序中出现的日期型数据的错误不是非常明显,不论使用都
语法错误的发现和处理是令人烦恼的,但在中会遇到一些真正“令人兴奋”的另一类型的错误——语义错误(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 inpidual date elements
intday = day(datbirthdate)
intmonth = month(datbirthdate)
intyear = year(datbirthdate)
and display them
response.write "day: " & cstr(intday) & "<br>"
response.write "month: " & cstr(intmonth) & "<br>"
response.write "year: " & cstr(intyear) & "<br>"
%>
图7-8是结果,是用美国日期风格月/日/年显示的,好像一切都没有问题。
图7-8 显示生日的屏幕
然而如果输入一个非法日期,或者让输入文本框空着,便得到一个运行期错误,如图7-9所示:
图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 inpidual date elements
intday = datbirthdate.getday();
intmonth = datbirthdate.getmonth();
intyear = datbirthdate.getyear();
// and display them
response.write("day: " + intday.tostring() + "<br>");
response.write("month: " + intmonth.tostring() + "<br>");
response.write("year: " + intyear.tostring() + "<br>");
%>
图7-10即是运行结果,尽管程序没有停止运行并给出运行期错误,还是马上看出其中有些问题,月份不可能是0。
图7-10 显示生日的屏幕
问题出现的原因在于jscript的getmonth函数返回的结果为0~11范围内的数,因此需要再加1,才能得到正确的结果。
intmonth = datbirthdate.getmonth() + 1;
(2) 衍生错误
即使不把初始值赋给网页去和结果比较,上面这种错误也可能是相当明显的。然而,如果面对的是一个数据库,并且没有看到显示出不正确的结果,可能不知道为什么程序不能正确地更新数据库。更糟糕的是,如果简单地把数值做为整型数据存入数据库,可能直到有人试图对这个数据查询时才能发现这个错误。
现在,发现大约有十二分之一的成员出生在0月份可能会使人吃惊,并会引起一些问题。记住,不仅仅是那些1月份出生的人员存在数据库中的信息不正确,而且每个成员都是这样。如果有许多应用程序都能增加和修改这个数据库中的记录,跟踪这个错误可能是艰苦的工作,特别是,不能去查找错误出现在哪个程序行,而是首先要找出错误出现在哪个应用程序中。
(3) 掌握日期的用法
在上面的程序中出现的日期型数据的错误不是非常明显,不论使用都
上一篇: ASP 3.0高级编程(二十七)
下一篇: 看什么呢?