Chinaopub coM 下载 第7章调试和错误处理 前面已经介绍了使用ASP所需要的基本技能,本章要讨论的另外一个问题是当ASP出现错 误时怎么办,ASP出错时是什么情况。当精心编排的ASP页面出现问题停止了执行时,用户 般得到的仅是一些用处不大的建议,诸如:点击“刷新”按钮,或者“与站点的web管理员 联系,告诉他们你的页面不能正常工作了”等等。 本章除了提供有用的信息源之外,还想提供一个帮助区域。我们将详细介绍在脚本和页 面中错误如何出现,可能产生的错误类型,以及什么造成了这些错误。更重要的是,要讨论 如何尽可能避免错误的发生,如不能避免又如何妥善处理 因此,本章将要探讨页面调试技术,也就是如何花费不多的精力和时间就能找到错误并 解决问题。 本章包括以下内容 能够出现的错误类型。 如何防止各种错误的产生 如果不能防止错误发生,如何妥善处理这些错误 如何发现和处理脚本错误及其他类型的错误。 如何使用定制的错误页面得到错误信息, 如何记录发生的错误以监视我们的网站 ·创建一个定制错误网页和一个错误日志文件。 提供相关的在线帮助 本章不涉及如何处理使用 ActiveX Data Objects(ADO)访问数据源时出现的各种特殊类型 的错误。像许多组件一样,ADO提供了自己的错误处理系统,第8章将深入讨论这一点。本章 将从讨论能出现的各种错误类型开始,使我们能够认识这些错误并采取相应的措施 据说,在非洲最黑暗的雨林深处,有这样一群程序员,他们的程序代码从来没有出现过 错误。但是,很遗憾他们从没有享受过调试一段不能正常工作的应用程序的乐趣。调试程序 代码是一个真正充满快乐的工作,所以我们要面对这个问题,在调试程序的过程中检验我们 的观察力和横向思维能力。大多数“真实世界”的程序员能够体验这些乐趣是一件好事。 当然,有些人会说,调试程序与其说是判断,不如说是碰运气。花费了许多时间去调试 段有错误的程序,在某种程度上可以说确实是依赖运气。但是,如果第一步从合适的地方 开始查看,可能会更快地解决问题 但这不是程序调试应采取的办法。从理论上讲,当某段程序运行失败时,应该以逻辑或 顺序方式跟踪错误。作为一个聪明和有经验的程序员,这才是调试时常用的方法,只有业余 人员才随意改变程序中变量的值,到处添加 Response. Write语句进行调试 然而,为了能够在逻辑上跟踪程序中的错误,必须了解有关错误如何出现方面的基础知 识,更重要的是知道错误出现在哪里,以便很快就能找到相应的地方。本章讨论的内容是有 关程序中能够出现的不同种类的错误,错误的不同表现,以及如何记录和排除这些错误。同
下载 第7章 调试和错误处理 前面已经介绍了使用A S P所需要的基本技能,本章要讨论的另外一个问题是当 A S P出现错 误时怎么办,A S P出错时是什么情况。当精心编排的 A S P页面出现问题停止了执行时,用户一 般得到的仅是一些用处不大的建议,诸如:点击“刷新”按钮,或者“与站点的 We b管理员 联系,告诉他们你的页面不能正常工作了”等等。 本章除了提供有用的信息源之外,还想提供一个帮助区域。我们将详细介绍在脚本和页 面中错误如何出现,可能产生的错误类型,以及什么造成了这些错误。更重要的是,要讨论 如何尽可能避免错误的发生,如不能避免又如何妥善处理。 因此,本章将要探讨页面调试技术,也就是如何花费不多的精力和时间就能找到错误并 解决问题。 本章包括以下内容: • 能够出现的错误类型。 • 如何防止各种错误的产生。 • 如果不能防止错误发生,如何妥善处理这些错误。 • 如何发现和处理脚本错误及其他类型的错误。 • 如何使用定制的错误页面得到错误信息。 • 如何记录发生的错误以监视我们的网站。 • 创建一个定制错误网页和一个错误日志文件。 • 提供相关的在线帮助。 本章不涉及如何处理使用 ActiveX Data Objects(ADO)访问数据源时出现的各种特殊类型 的错误。像许多组件一样, A D O提供了自己的错误处理系统,第 8章将深入讨论这一点。本章 将从讨论能出现的各种错误类型开始,使我们能够认识这些错误并采取相应的措施。 据说,在非洲最黑暗的雨林深处,有这样一群程序员,他们的程序代码从来没有出现过 错误。但是,很遗憾他们从没有享受过调试一段不能正常工作的应用程序的乐趣。调试程序 代码是一个真正充满快乐的工作,所以我们要面对这个问题,在调试程序的过程中检验我们 的观察力和横向思维能力。大多数“真实世界”的程序员能够体验这些乐趣是一件好事。 当然,有些人会说,调试程序与其说是判断,不如说是碰运气。花费了许多时间去调试 一段有错误的程序,在某种程度上可以说确实是依赖运气。但是,如果第一步从合适的地方 开始查看,可能会更快地解决问题。 但这不是程序调试应采取的办法。从理论上讲,当某段程序运行失败时,应该以逻辑或 顺序方式跟踪错误。作为一个聪明和有经验的程序员,这才是调试时常用的方法,只有业余 人员才随意改变程序中变量的值,到处添加 R e s p o n s e . Wr i t e语句进行调试。 然而,为了能够在逻辑上跟踪程序中的错误,必须了解有关错误如何出现方面的基础知 识,更重要的是知道错误出现在哪里,以便很快就能找到相应的地方。本章讨论的内容是有 关程序中能够出现的不同种类的错误,错误的不同表现,以及如何记录和排除这些错误。同
hina-pub.com 第7章调试和错误处理 211 样重要的是,还将介绍如何避免这些错误的发生 本章将从介绍可能出现的不同种类的错误开始,如果认为你的代码不会出现任何错误, 可以直接跳到下一章 7.1错误的种类 7.1.1语法或“编译”错误 当我们第一次运行新编写的程序代码时,通常看到的第一种错误类型是“ syntax error" 这就是所说的,程序代码上的语法错误。这就像在写作中使用了错误的语法,使读者不能了 解其中的含义。而解释器(诸如脚本引擎)和编译器对语法要求得更加严格和准确。 语法错误通常也是最早出现和需要排除的。大多数情况下,解释器和编译器会指出行号 和所在行中的字符位置,以及在相应的位置上缺少的内容。下面举一个简单的例子,如下所 示的这样一段程序 Response. Write The repayments for your loan are $'& curPayment strInterval & due on the . strAy &.of each 我们希望得到下面的结果 The repayments for your loan are $124. 50 per month, due on the 12th of each month 实际上得到的结果如图7-1所示。 i mage cannot he displayed 作 ra netcca nh IP sne tau. hdad seer Lrer, ae,am trend wurrvatee tt wgen wwan t; Sten ffec详 图7-1程序执行结果1 文件中第3行是 Response. Write语句的第2行。报告错误信息时,Ⅴ SCript解释器忽略一行 中的引导空格和制表符。所以在数完26个字符之后,可以找到语法错误的地方,这里明显缺 了一个双引号。加上双引号后再运行这个页面,我们可以得到如图7-2所示的画面
样重要的是,还将介绍如何避免这些错误的发生。 本章将从介绍可能出现的不同种类的错误开始,如果认为你的代码不会出现任何错误, 可以直接跳到下一章。 7.1 错误的种类 7.1.1 语法或“编译”错误 当我们第一次运行新编写的程序代码时,通常看到的第一种错误类型是“ syntax error”。 这就是所说的,程序代码上的语法错误。这就像在写作中使用了错误的语法,使读者不能了 解其中的含义。而解释器(诸如脚本引擎)和编译器对语法要求得更加严格和准确。 语法错误通常也是最早出现和需要排除的。大多数情况下,解释器和编译器会指出行号 和所在行中的字符位置,以及在相应的位置上缺少的内容。下面举一个简单的例子,如下所 示的这样一段程序: 我们希望得到下面的结果: 实际上得到的结果如图7 - 1所示。 图7-1 程序执行结果1 文件中第3行是R e s p o n s e . Write 语句的第2行。报告错误信息时,V B S c r i p t解释器忽略一行 中的引导空格和制表符。所以在数完 2 6个字符之后,可以找到语法错误的地方,这里明显缺 少了一个双引号。加上双引号后再运行这个页面,我们可以得到如图 7 - 2所示的画面。 第7章 调试和错误处理计计2 1 1 下载
212Ap高箱程 China pub coM 下载 TP 5D0 1D0.Internal Server Error. ASP erm Internet Informaton Services Technical into (for support personnel) 优st,dsp,Ine4 图72程序执行结果2 这次又是另外一个简单错误。实际上错误出现在第3行而不是第4行。我们漏掉了第三行 末尾的续行符'。程序代码应该是: Response. Write " The repayments for your loan are $.& curP due yk· of each s strinterval S 错误出现在什么地方 需要注意的是脚本解释器仅指出所发现错误的地方,但实际上那儿并不一定是错误真正 出现的地方。在上例中,前面三行的语法正确的,并产生相应的输出结果,而恰恰是第4行引 起问题,因为这一行是以一种非法字符开头的,脚本解释器没有意识到这一行是上一行的 部分。 这样的错误是普遍存在的,因为通常我们主要考虑的是要输出的文本内容,而不是双引 号、连字符(在 VBScript中为"&")、续行符等的正确顺序。 对于关键字、内部函数名拼写错误或函数的非法参数列表而引起的语法错误,通常比较 容易发现,因为错误信息提示可能就指出了错误的实际位置。例如:下面这段代码是想把明 天的日期写入页面。 Response. write DateAdd(Now(),"d', 1) 实际得到结果的如图7-3所示 Http 500.100.internal Server Error Asp error Internet Information Services Technical Information (for support personnel) Error Type match:'[string: "d"] /test/test. asp, line 2 图7-3程序执行结果3 这是因为 DataAdd函数的语法应该是: DateAdd (interval_string, interval__number, start date
图7-2 程序执行结果2 这次又是另外一个简单错误。实际上错误出现在第 3行而不是第4行。我们漏掉了第三行 末尾的续行符' _ '。程序代码应该是: 1. 错误出现在什么地方 需要注意的是脚本解释器仅指出所发现错误的地方,但实际上那儿并不一定是错误真正 出现的地方。在上例中,前面三行的语法正确的,并产生相应的输出结果,而恰恰是第 4行引 起问题,因为这一行是以一种非法字符开头的,脚本解释器没有意识到这一行是上一行的一 部分。 这样的错误是普遍存在的,因为通常我们主要考虑的是要输出的文本内容,而不是双引 号、连字符(在V B S c r i p t中为" & " )、续行符等的正确顺序。 对于关键字、内部函数名拼写错误或函数的非法参数列表而引起的语法错误,通常比较 容易发现,因为错误信息提示可能就指出了错误的实际位置。例如:下面这段代码是想把明 天的日期写入页面。 实际得到结果的如图7 - 3所示。 图7-3 程序执行结果3 这是因为D a t a A d d函数的语法应该是: 212计计ASP 3 高级编程 下载
chinaopub.com 第章调试和错误处理213 所以应该改写为如下的代码: Response. write DateAdd(d, 1, Now()) 脚本解释器检测到了我们为第二个参数提供的是一个字符型数据,而 DataAdd函数需要的 是整型数据类型。 代码结构和脚本结构 语法错误的另一个原因是:当制作网页时使用嵌套的或复杂的脚本结构,如 If Then.Els End If或者 Do While.Loop。这有时会造成难以找到的语法错误 例如下面这段程序 If Len(Request Form('cmdSet ))Then strCounterName- Request Form("Isset") strNewvalue =a Request Form('txtset) If IsNumeric(strNewValue)Then ntNewvalue CInt(strNewvalue bjcounters. set strcounterName intNewvalue Response. Write ' Set counter . strcounterName to . strNewvalue Response. Write strNewvalue &' is not a valid If Len(Request Form('cmaRemove))Then objCounters. Remove strcounterName Response. Write Removed counter strcounterName Ena工f End If 产生的错误如图7-4所示 TP 500,100. Internal Server Error. AsP e nternet Informaton Service echnical Information (for support personnel) Error Type Mpected'End /test/test. asp, line 16 国国L 图74程序执行结果4 为什么提示在网页程序中需要一个End语句呢?看一下程序就可以发现,丢失了一个End If,而不是End,在程序的最末尾应该还有另一个 End if o Response. Write Removed counter ' strCounterName End If 在这种情况下,根据代码的缩排格式可以很容易地找到相应的错误。特别当错误信息指 出错误的大致位置时,很快就可以找到错误位置。然而,这段代码很短,如果在分界符 中另外还有40行代码,那么错误行号仍然可能指向最后一行(line56):并且如果在新
所以应该改写为如下的代码: 脚本解释器检测到了我们为第二个参数提供的是一个字符型数据,而 D a t a A d d函数需要的 是整型数据类型。 代码结构和脚本结构 语法错误的另一个原因是:当制作网页时使用嵌套的或复杂的脚本结构,如 If Then...Else ...End If 或者Do While...Loop。这有时会造成难以找到的语法错误。 例如下面这段程序: 产生的错误如图7 - 4所示。 图7-4 程序执行结果4 为什么提示在网页程序中需要一个 E n d语句呢?看一下程序就可以发现,丢失了一个 E n d I f,而不是E n d,在程序的最末尾应该还有另一个 End If。 在这种情况下,根据代码的缩排格式可以很容易地找到相应的错误。特别当错误信息指 出错误的大致位置时,很快就可以找到错误位置。然而,这段代码很短,如果在分界符 中另外还有4 0行代码,那么错误行号仍然可能指向最后一行 (line 56);并且如果在新 第7章 调试和错误处理计计2 1 3 下载
214Ap高箱程 Chinaspub. coM 下载 的代码中的其他脚本结构搞乱了嵌套的结构,错误可能会指向另一个位置 2.关于 JScript 如果你不是一位 JavaScript高手,并且确实想试验一些语法错误,那么就从 SCript切换 到 JScript. JScript比Ⅴ SCript对程序编写的要求更严格,并且对关键字和变量名大小写敏感, 看下面的程序段 Response. Write(datToday. GetMonth()) 运行这段程序会产生" Object doesn't support this property or method"(对象不支持这种属性 或方法)错误,如图7-5所示。 rmal Server Error. ASP error Technical Information(for support personnel) Error Type ft Script runtime(Ox800A0186) Object doesn't support this property or method /test/test. asp, line 4 图7-5程序执行结果5 原因很简单,返回目前月份数的 JScript函数是 getMonth,而不是 GetMonth。下面这段程 序就可以正常运行。 var datroday new Date( Response. write(datToday. getMonth()); 当然,如果重试这段程序,可能得不到同样的错误消息。我们第一次运行这段程序时 得到如图7-6所示的错误。 Error Type: /test/test, asp, line 2, column 2 图76程序执行结果6 第2行有什么错误?如果使用 JScript解释器,没有错误出现。错误消息说明,这是一个 Ⅴ SCript语法错误。用Ⅴ SCript解释器分析 JScript程序,所以会得到奇怪的错误消息← 记住正在使用的语言 之所以出现上述错误是因为在页面的代码前面记了加 LANGUaGE指令。缺省是 Ⅴ SCript(如果在注册表或在 Internet Services Manager中没有改变它),所以Ⅴ SCript引擎用于 处理前面不带@ LANGUAGE指令的程序。即使一直使用专为自已的服务器设置的缺省语言
的代码中的其他脚本结构搞乱了嵌套的结构,错误可能会指向另一个位置。 2. 关于J S c r i p t 如果你不是一位 J a v a S c r i p t高手,并且确实想试验一些语法错误,那么就从 V B S c r i p t切换 到J S c r i p t。J S c r i p t比V B S c r i p t对程序编写的要求更严格,并且对关键字和变量名大小写敏感, 看下面的程序段。 运行这段程序会产生"Object doesn't support this property or method"(对象不支持这种属性 或方法)错误,如图7 - 5所示。 图7-5 程序执行结果5 原因很简单,返回目前月份数的 JScript 函数是g e t M o n t h,而不是G e t M o n t h。下面这段程 序就可以正常运行。 当然,如果重试这段程序,可能得不到同样的错误消息。我们第一次运行这段程序时, 得到如图7 - 6所示的错误。 图7-6 程序执行结果6 第2行有什么错误?如果使用 J S c r i p t解释器,没有错误出现。错误消息说明,这是一个 V B S c r i p t语法错误。用V B S c r i p t解释器分析J S c r i p t程序,所以会得到奇怪的错误消息。 记住正在使用的语言 之所以出现上述错误是因为在页面的代码前面记了加 @ L A N G U A G E指令。缺省是 V B S c r i p t (如果在注册表或在Internet Services Manager中没有改变它),所以V B S c r i p t引擎用于 处理前面不带 @ L A N G U A G E指令的程序。即使一直使用专为自已的服务器设置的缺省语言, 214计计ASP 3 高级编程 下载
china-pub.com 第章调试和误处理215 使用@ OLANGUAGE指令是避免产生上述错误的好方法。这样,如果把网页移到另一个缺 言不同的服务器上,也会得到预期的结 这里讲述的内容不可能覆盖所有可能遇到的语法错误,人们往往想知道为什么会出现错 误,而错误信息提示并不总是像人们希望的那样准确。理想的方式应该是ASP给我们提供 个简洁的错误显示页面,有对错误的全面精确的描述,甚至询问我们是否想自动处理错误。 事实上应用程序 Microsoft Script Debugger正试图为我们提供类似的功能,本章后面要对 其进行讨论,也要概括避免出现语法错误的一些要点。现在,我们继续研究经常在网页中出 现的第二类错误。 7.1.2语义或“运行期”错误 语法错误的发现和处理是令人烦恼的,但在编程中会遇到一些真正“令人兴奋”的另 类型的错误——,语义错误( semantic error)或称“运行期”错误( runtime error)。这类错误仅 当运行一个脚本代码或其他程序时才会发现。换句话说,完整有效的代码已经通过解释器或 编译器的解释或编译,在执行时产生了错误。术语“运行期错误”通常是指语义错误的结果, 也就是说这类错误存在于代码中的语义中,当代码运行时它们才变成可见的 这种区别来自于这种事实:程序编译器或解释器在处理程序代码之前必须建立一种内部 代码的描述,涉及多种结构开头和结尾的匹配,以便标明每种结构包含什么内容,然后分析 每个句子,以便知道如何执行这个句子。例如,如果在程序代码中有一个 IF Then Else.ndIf结构,解释器或编译器做的第一步工作就是分析哪些语句在“Then”的部分,哪 些在“Ese”部分。这一步的目的是,在对结构中的IF条件进行测试之后,可以决定该到哪个 分支去执行。 编译器(诸如在编程语言像 Visual basic和C艹+中见到的那种)和解释器(诸如用于像 Ⅴ SCript和 JScript那样的脚本语言的解释器)之间真正区别在于:编译器不试图运行程 序代码,而是在对源程序进行两次预处理后,形成二进制指令或符号代码,并形成 个exe文件或d文件。解释器不创建含有代码的文件,而是在运行时逐行执行。 使运行停止的错误 如果程序中含有一个语义错误,通常在运行时可得到提示。如果幸运的话,当错误发生 程序会停止,这样可以容易地找出错误所在。例如,下面这段程序定义了一个有六个元 素的数组 Dim arrValues(5) 'to hold six elements, indexed from0 to 5 arrValues(6)="Whoops, got 如果试图读或设置下标为6的元素值,可以得到一个运行期错误,如图7-7所示 Microsoft VBScript runtime(0x800A000 Subscript out of range: 'Inumber: 6] /test/test. asp, line 3 图7-7程序执行结果6
始终使用@ L A N G U A G E指令是避免产生上述错误的好方法。这样,如果把网页移到另一个缺 省语言不同的服务器上,也会得到预期的结果。 这里讲述的内容不可能覆盖所有可能遇到的语法错误,人们往往想知道为什么会出现错 误,而错误信息提示并不总是像人们希望的那样准确。理想的方式应该是 A S P给我们提供一 个简洁的错误显示页面,有对错误的全面精确的描述,甚至询问我们是否想自动处理错误。 事实上应用程序Microsoft Script Debugger正试图为我们提供类似的功能,本章后面要对 其进行讨论,也要概括避免出现语法错误的一些要点。现在,我们继续研究经常在网页中出 现的第二类错误。 7.1.2 语义或“运行期”错误 语法错误的发现和处理是令人烦恼的,但在编程中会遇到一些真正“令人兴奋”的另一 类型的错误—,语义错误(semantic error)或称“运行期”错误 (runtime error)。这类错误仅 当运行一个脚本代码或其他程序时才会发现。换句话说,完整有效的代码已经通过解释器或 编译器的解释或编译,在执行时产生了错误。术语“运行期错误”通常是指语义错误的结果, 也就是说这类错误存在于代码中的语义中,当代码运行时它们才变成可见的。 这种区别来自于这种事实:程序编译器或解释器在处理程序代码之前必须建立一种内部 代码的描述,涉及多种结构开头和结尾的匹配,以便标明每种结构包含什么内容,然后分析 每个句子,以便知道如何执行这个句子。例如,如果在程序代码中有一个 IF Then ... Else...End If结构,解释器或编译器做的第一步工作就是分析哪些语句在“ T h e n”的部分,哪 些在“E l s e”部分。这一步的目的是 ,在对结构中的I F条件进行测试之后,可以决定该到哪个 分支去执行。 编译器(诸如在编程语言像Visual Basic和C + +中见到的那种)和解释器(诸如用于像 V B S c r i p t和J S c r i p t那样的脚本语言的解释器)之间真正区别在于:编译器不试图运行程 序代码,而是在对源程序进行两次预处理后,形成二进制指令或符号代码,并形成一 个. e x e文件或. d l l文件。解释器不创建含有代码的文件,而是在运行时逐行执行。 1. 使运行停止的错误 如果程序中含有一个语义错误,通常在运行时可得到提示。如果幸运的话,当错误发生 时,程序会停止,这样可以容易地找出错误所在。例如,下面这段程序定义了一个有六个元 素的数组。 如果试图读或设置下标为6的元素值,可以得到一个运行期错误,如图 7 - 7所示。 图7-7 程序执行结果6 第7章 调试和错误处理计计2 1 5 下载
216Ap高箱程 Chinapub.com 下载 注意这里的错误类型是“ runtime”(相当于语义)错误,而不是语法错误。错误信息显示 了错误所在行数和错误的描述,有助于我们比较容易地找到相应的错误。但这是一个简单的 例子,在更复杂的程序代码中,这种错误可能出现在一些遍历一些值并把它们加到一个数组 中的程序中。如下所示 Dim arrvalues(5) "t。bo1daxe18 For intLoop 0 To intListcount the number of item in let rrvalues(intLoop)= Request Form("SelectedItems )(intListcount) 这种情况下,很可能是得到了过多的列表条目,或者是数组的索引不够,根据代码的要 求,可以判断是那种错误,并且能够通过增加数组大小来解决这个错误 Dim arrvalues (10) to bola eleven elemente For intLoop =0 To intListcount he number of items in some list arrValues (intLoop)- Request Form("SelectedItems)(intListcount Next 或者相应地设置循环的参数来解决处理这个错误 to hold six elements intArrayMax intListcount If intArrayMax 5 Then intArrayMax =5 For intLoop =0 To intArrayMax only add the first slx 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 ") get the individual date elements intMonth Month(datBirthdate) intYear Year(datBirthdate) Response. Write Day: cstr(intDay)&.. Response. Write ' Month: cStr(intMonth)&.. Response. Write 'Year:*& cstr(intyear)&
注意这里的错误类型是“ r u n t i m e”(相当于语义 )错误,而不是语法错误。错误信息显示 了错误所在行数和错误的描述,有助于我们比较容易地找到相应的错误。但这是一个简单的 例子,在更复杂的程序代码中,这种错误可能出现在一些遍历一些值并把它们加到一个数组 中的程序中。如下所示。 这种情况下,很可能是得到了过多的列表条目,或者是数组的索引不够,根据代码的要 求,可以判断是那种错误,并且能够通过增加数组大小来解决这个错误。 或者相应地设置循环的参数来解决处理这个错误。 许多其他运行期错误能够使网页运行停止,诸如一些组件或对象的实例化失败,原因是 有P r o g I D错误,或者是因为组件没有正确安装。在这些情况下,结果总是给出 " A c t i v e X Cannot Create Object"错误提示信息,后面跟着调用 S e r v e r. C r e a t e O b j e c t方法的行号。 2. 产生错误结果的错误 上面提到,如果遇到一个使程序代码停止的运行期错误,我们可能是幸运的。但是另一 种情况是程序能很好地执行,好像什么也没有发生,最后产生一个错误的结果。这是最难发 现和解决的错误,因为意识不到哪里出错了。例如,假设有一个网页,这个网页把用户的生 日作为日期型的值,并且单独显示日期元素 (可以把它们作为三个条目加到一个数据库中 )。 216计计ASP 3 高级编程 下载
第7章调试和错误处理 217 图7-8是结果,是用美国日期风格月/日/年显示的,好像一切都没有问题。 然而如果输入一个非法日期,或者让输入文本框空着,便得到一个运行期错误,如图7-9 a htp.//w Technical Information (for support personnel) The value you entered i: 1/27/69 Error Type crosoft VBScnpt runtime(0x800A000D) Day: 27 Type mismatch: [string: I /test/test. asp, line 18 国L0cam由 图78显示生日的屏幕 图7-9错误提示屏幕 (1)如果不是一位 jscript专家 在寻找错误时,这不是一个大问题,因为我们能够迅速发现为什么会出现错误。事实上 网页停止运行有助于我们跟踪错误。然而意外的错误可能会发生。例如,用 JScript重写程序 代码,由于不是一位 JScript专家,里面出现一些细小错误 // get the value from the Request and display t var datBirthdate new Date(Request Form("BirthDate)) Response. write(The value you entered is: . datBirthdate +." / et the individual date elements ntDay datBirthdate. getDay (); intMonth u datBirthdate. getMonth( ntYear datBirthdate. getYear()i 1/ and diaplay intDay. tostring()+.") h:·+ intMonth. tostring()+·); Response. write( intYear. tostring()+"'): 图7-10即是运行结果,尽管程序没有停止运行并给出运行期错误,还是马上看出其中有 些问题,月份不可能是0 The value you entered is: Mon Jan 27 00: 00: 00 UTC 1969 Month: 0 图7-10显示生日的屏幕 问题出现的原因在于 JScript的 get month函数返回的结果为0~11范围内的数,因此需要再 加1,才能得到正确的结果。 intMonth datBirthdate. getMonth()+1;
图7 - 8是结果,是用美国日期风格月 /日/年显示的,好像一切都没有问题。 然而如果输入一个非法日期,或者让输入文本框空着,便得到一个运行期错误,如图 7 - 9 所示。 (1) 如果不是一位J S c r i p t专家 在寻找错误时,这不是一个大问题,因为我们能够迅速发现为什么会出现错误。事实上 网页停止运行有助于我们跟踪错误。然而意外的错误可能会发生。例如,用 J S c r i p t重写程序 代码,由于不是一位J S c r i p t专家,里面出现一些细小错误。 图7 - 1 0即是运行结果,尽管程序没有停止运行并给出运行期错误,还是马上看出其中有 些问题,月份不可能是0。 图7-10 显示生日的屏幕 问题出现的原因在于 J S c r i p t的g e t M o n t h函数返回的结果为 0 ~ 11范围内的数,因此需要再 加1,才能得到正确的结果。 第7章 调试和错误处理计计2 1 7 下载 图7-8 显示生日的屏幕 图7-9 错误提示屏幕
218 ASP3高级编程 China-pub. coM 下载 (2)衍生错误 即使不把初始值赋给网页去和结果比较,上面这种错误也可能是相当明显的。然而,如 果面对的是一个数据库系统,并且没有看到显示出不正确的结果,可能不知道为什么程序不 能正确地更新数据库。更糟糕的是,如果简单地把数值做为整型数据存入数据库,可能直到 有人试图对这个数据查询时才能发现这个错误 现在,发现大约有十二分之一的成员出生在0月份可能会使人吃惊,并会引起一些问题 记住,不仅仅是那些1月份出生的人员存在数据库中的信息不正确,而且每个成员都是这样。 如果有许多应用程序都能増加和修改这个数据库中的记录,跟踪这个错误可能是艰苦的工作 特别是,不能去査找错误出现在那个程序行,而是首先要找出错误出现在哪个应用程序中 (3)掌握日期的用法 在上面的程序中出现的日期型数据的错误不是非常明显,不论使用者输入什么样的日期, 程序代码只能给出0-6之中的值,原因在于编码中的设定,特别是从 VBScript转换到 JScript时 在 JScript中, getDay函数返回的是周中的某一天,而不是月中的某一天,这等价于 VBScript中 的 Weekday函数, getDay函数的返回值是0代表星期日)到6(代表星期六) 注意 VBScript的 Weekday函数返回1(代表星期日)到7(代表星期六) 因此,在 jscript'中由 getDate函数获得某月的日期的正确代码是 / get the individual date elements intDay datBirthdate. getDate(); intMonth datBirthdate. getMonth ()+1: intYear datBirthdate. getYear(); 运行这段程序便可得到想要的结果,如图7-11所示。 The value you entered is: Mon Jan 27 00: 00: 00 UTC 1969 Month Year: 69 图7-11显示正确生日的屏幕 7.2各种运行期错误 本章前面部分展示了一些问题,包括错误如何出现、如何寻找错误和如何处理错误等等 现在更重要的是要掌握能够发生的不同种类的错误,并且如何区分这些错误。需要记住的是, 如果知道了到哪里去找和寻找什么,调试则是比较容易的。在本章最后,将介绍错误确实出 现时如何捕获错误,并且要尽可能早地阻止错误的发生。 在学习这些内容之前,首先要深入了解一下在某个阶段肯定会遇到的不同类型的运行期 和语义错误,主要讨论以下内容 逻辑错误
(2) 衍生错误 即使不把初始值赋给网页去和结果比较,上面这种错误也可能是相当明显的。然而,如 果面对的是一个数据库系统,并且没有看到显示出不正确的结果,可能不知道为什么程序不 能正确地更新数据库。更糟糕的是,如果简单地把数值做为整型数据存入数据库,可能直到 有人试图对这个数据查询时才能发现这个错误。 现在,发现大约有十二分之一的成员出生在 0月份可能会使人吃惊,并会引起一些问题。 记住,不仅仅是那些 1月份出生的人员存在数据库中的信息不正确,而且每个成员都是这样。 如果有许多应用程序都能增加和修改这个数据库中的记录,跟踪这个错误可能是艰苦的工作, 特别是,不能去查找错误出现在那个程序行,而是首先要找出错误出现在哪个应用程序中。 (3) 掌握日期的用法 在上面的程序中出现的日期型数据的错误不是非常明显,不论使用者输入什么样的日期, 程序代码只能给出0 ~ 6之中的值,原因在于编码中的设定,特别是从 V B S c r i p t转换到J S c r i p t时。 在J S c r i p t中,g e t D a y函数返回的是周中的某一天,而不是月中的某一天,这等价于 V B S c r i p t中 的We e k d a y函数,g e t D a y函数的返回值是0 (代表星期日)到6 (代表星期六)。 注意V B S c r i p t的We e k d a y函数返回1 (代表星期日)到7 (代表星期六)。 因此,在J s c r i p t中由g e t D a t e函数获得某月的日期的正确代码是: 运行这段程序便可得到想要的结果,如图 7 - 11所示。 图7 - 11 显示正确生日的屏幕 7.2 各种运行期错误 本章前面部分展示了一些问题,包括错误如何出现、如何寻找错误和如何处理错误等等。 现在更重要的是要掌握能够发生的不同种类的错误,并且如何区分这些错误。需要记住的是, 如果知道了到哪里去找和寻找什么,调试则是比较容易的。在本章最后,将介绍错误确实出 现时如何捕获错误,并且要尽可能早地阻止错误的发生。 在学习这些内容之前,首先要深入了解一下在某个阶段肯定会遇到的不同类型的运行期 和语义错误,主要讨论以下内容: • 逻辑错误。 218计计ASP 3 高级编程 下载
hinapub.com 第7章调试和错误处理 219 脚本运行期错误 ·ASP和SSI运行期错误 ·客户端脚本错误 7.2.1逻辑错误 逻辑错误在脚本中通常难于跟踪,因为这些错误常常是产生错误的结果而不中止网页运 行。通常只有一些值出现超出边界的情况,如在前面数组实例中看到的那样,错误才显现出 然而,在错误和调试环境中,一种算法并不像数学课上所学的那样复杂。从计算的角度 看,算法只是指一段能完成某个任务(通常返回某个结果)的程序 数值超界(数据溢出) 典型的逻辑错误一般涉及到数值,或者是涉及数据溢出等。例如,如果有名为 image 1.gif、 mage2.gif等的一系列图像,编写以下一段程序随机挑选一幅图象用以显示: create a random umber between 1 and 5 intRandom= CInt(Rnd()*5)+1 IMG SRC.="> 在网页中创建元素用以指定随机选中的图象,例如 然而,如果碰巧这段程序产生的结果是 Image6.gif文件。在这种情况下,如果本来仅希望 得到在1~5中的一个结果,网页会是一个破碎的图像符号。原因是Ⅴ SCript中的Cnt函数将值 取整到最近的整数值。为了舍去小数部分,需要使用Int或者Fⅸx函数代替CInt 2.运算符号的优先级 其他类型的逻辑错误有按指令计算而出现的错误,例如想用除法时采用了乘法会产生错 误的结果。而由于程序中数学运算符号的运行顺序或优先级,会引起一些更难发现的错误 例如,下面这段程序可能会产生不正确的结果 intResult e intvaluel intValue2 intvalue3 因为乘法比加法有较高的运算优先级,所以先进行计算。但是如果想把第一个数和后两 个数的和相乘,必须用括号来改变这种缺省的运算优先权 intResult intValuel *(intvalue2 +intvalue3) 在 VBScript50文档中的 VBScript Basics/VBScript Operators中,给出了所有脚本运算符号 的优先级表。对于 JScript,在 JScript Tutorial JScript Basics JScript Operators下也可找到相应 的优先级表。然而需要记住的最基本原则是:乘、除法优先于加、减法。 管理和格式化字符串数据 从计算意义上考虑,具有计算功能的任何结构或函数都可看作一种算法。例如,可以从 数据库中取值构成一个字符串,代表顾客的名字。这里不涉及如何从数据库中提取数据(本书 的后面部分进行讨论)。下面程序的功能是字符串连接 trritle iget from dat strFirstName = iget from database strMiddleInitial - iget from database)
• 脚本运行期错误。 • ASP和S S I运行期错误。 • 客户端脚本错误。 7.2.1 逻辑错误 逻辑错误在脚本中通常难于跟踪,因为这些错误常常是产生错误的结果而不中止网页运 行。通常只有一些值出现超出边界的情况,如在前面数组实例中看到的那样,错误才显现出 来。 然而,在错误和调试环境中,一种算法并不像数学课上所学的那样复杂。从计算的角度 看,算法只是指一段能完成某个任务 (通常返回某个结果)的程序。 1. 数值超界(数据溢出) 典型的逻辑错误一般涉及到数值,或者是涉及数据溢出等。例如,如果有名为 i m a g e 1 . g i f、 i m a g e 2 . g i f等的一系列图像,编写以下一段程序随机挑选一幅图象用以显示: 在网页中创建<I M G>元素用以指定随机选中的图象,例如: 然而,如果碰巧这段程序产生的结果是 i m a g e 6 . g i f文件。在这种情况下,如果本来仅希望 得到在1 ~ 5中的一个结果,网页会是一个破碎的图像符号。原因是 V B S c r i p t中的C I n t函数将值 取整到最近的整数值。为了舍去小数部分,需要使用 I n t或者F i x函数代替C I n t。 2. 运算符号的优先级 其他类型的逻辑错误有按指令计算而出现的错误,例如想用除法时采用了乘法会产生错 误的结果。而由于程序中数学运算符号的运行顺序或优先级,会引起一些更难发现的错误, 例如,下面这段程序可能会产生不正确的结果。 因为乘法比加法有较高的运算优先级,所以先进行计算。但是如果想把第一个数和后两 个数的和相乘,必须用括号来改变这种缺省的运算优先权。 在VBScript 5.0文档中的VBScript Basics|VBScript Operators中,给出了所有脚本运算符号 的优先级表。对于J S c r i p t,在JScript Tutorial|JScript Basics|JScript Operators下也可找到相应 的优先级表。然而需要记住的最基本原则是:乘、除法优先于加、减法。 3. 管理和格式化字符串数据 从计算意义上考虑,具有计算功能的任何结构或函数都可看作一种算法。例如,可以从 数据库中取值构成一个字符串,代表顾客的名字。这里不涉及如何从数据库中提取数据 (本书 的后面部分进行讨论)。下面程序的功能是字符串连接。 第7章 调试和错误处理计计2 1 9 下载