各種運行期錯誤

來源:互聯網
上載者:User
錯誤


    本章前面部分展示了一些問題,包括錯誤如何出現、如何尋找錯誤和如何處理錯誤等等。現在更重要的是要掌握能夠發生不同種類的錯誤,並且如何區分這些錯誤。需要記住的是,如果知道了到哪裡去找和尋找什麼,調試則是比較容易的。在本章最後,將介紹錯誤確實出現時如何捕獲錯誤,並且要儘可能早地阻止錯誤的發生。
       在學習這些內容之前,首先要深入瞭解一下在某階段肯定會遇到的不同類型的運行期和語義錯誤,主要討論以下內容:
       · 邏輯錯誤。
       · 指令碼運行期錯誤。
       · ASP和SSI運行期錯誤。
       · 用戶端指令碼錯誤。

7.2.1 邏輯錯誤
       邏輯錯誤在指令碼中通常難於跟蹤,因為這些錯誤常常是產生錯誤的結果而不中止網頁運行。通常只有一些值出現超出邊界的情況,如在前面數組執行個體中看到的那樣,錯誤才顯現出來。
       然而,在錯誤和調試環境中,一種演算法並不像數學課上所學的那樣複雜。從計算的角度看,演算法只是指一段能完成某個任務(通常返回某個結果)的程式。
1.  數值超界(資料溢出)
典型的邏輯錯誤一般涉及到數值,或者是涉及資料溢出等。例如,如果有名為image1.gif、image2.gif等一系列映像,編寫以下一段程式隨機挑選一幅映像用以顯示:
<%
' create a random number between 1 and 5
intRandom = CInt(Rnd() * 5) +1
%>
<IMG SRC="<% = "image” & CStr(intRandom) & ".gif" %>">
在網頁中建立<IMG>元素用以指定隨機選中的映像,例如:
<IMG SRC=http://www.163design.net/a/j/"image3.gif">
然而,如果碰巧這段程式產生的結果是image6.gif檔案。在這種情況下,如果本來僅希望得到在1~5中的一個結果,網頁會是一個破碎的映像符號。原因是VBScript中的CInt函數將值取整到最近的整數值。為了捨去小數部分,需要使用Int或者Fix函數代替CInt。
2.  運算子號的優先順序
其他類型的邏輯錯誤有按指令計算而出現的錯誤,例如想用除法時採用了乘法會產生錯誤的結果。而由於程式中數學運算子號的運行順序或優先順序,會引起一些更難發現的錯誤,例如,下面這段程式可能會產生不正確的結果。
intResult = intValue1 * intValue2 + intValue3
因為乘法比加法有較高的運算優先順序,所以先進行計算。但是如果想把第一個數和後兩個數的和相乘,必須用括弧來改變這種預設的運算優先權。
intResult = intValue1 * (intValue2 + intValue3)
在VBScript 5.0文檔中的VBScript Basics| VBScript Operators中,給出了所有指令碼運行符號的優先順序表。對於JScript,在JScript Tutorial|JScript Basic|JScript Operators下也可找到相應的優先順序表。然而需要記住的最基本原則是:乘、除法優先於加、減法。
3.  管理和格式化字串資料
從計算意義上考慮,具有計算功能的任何結構或函數都可看作一種演算法。例如,可以從資料庫中取值構成一個字串,代表顧客的名字。這裡不涉及如何從資料庫中提取資料(本書的後面部分進行討論)。下面程式的功能是字串串連。
strTitle = {get from database}
strFirstName = {get from database}
strMiddleInitial = {get from database}
strLastName = {get from database}
strOther = {get from database}

strPrint = strTitle & ". " & strFristName & " " & strMiddleInitial _
              & ". " & strstrLastName & " " & strOther
運行這段程式可以得到如下結果:
Ms. Janet C. Clarke MBNA.BSc.MechEng.
但不是每個人都和“Janet”一樣,有一個中間名字。並且許多人可能沒有頭銜,所以可能僅僅得到:
. Alex . Homer
這當然不是一個能引起指令碼不能運行或者產生運行期錯誤的致命錯誤。然而,對於使用者來說,提供這樣的指令碼是不可接受的。最好程式能在輸出字串之前檢查名字的每一部分。

strPrint = ""
If Len(strTitle) Then strPrint = strPrint & strTitle & ". "
If Len(strFirstName) Then strPrint = strPrint & strFirstName & " "
If Len(strMiddleInitial) Then strPrint = strPrint & strMiddleInitial & ". "
If Len(strLastName) Then strPrint = strPrint & strLastName
If Len(strOther) Then strPrint = strPrint & " " & strOther
上面這段程式保證了空格和小數點僅加在名字中有值的地方。如果僅給strOther字串賦值,而對其他都不賦值的話,將在開始處得到一個空格。然而出現這種情況的可能性非常小。如果有姓的話,通過僅添加“Other”部分可以防止這種錯誤的發生。


strPrint = ""
If Len(strTitle) Then strPrint = strPrint & strTitle & ". "
If Len(strFirstName) Then strPrint = strPrint & strFirstName & " "
If Len(strMiddleInitial) Then strPrint = strPrint & strMiddleInitial & ". "
If Len(strLastName) Then
strPrint = strPrint & strLastName
If Len(strOther) Then strPrint = strPrint & " " & strOther
       End If
最壞的情況是結果為一個Null 字元串,可以檢查這種可能性並中止列印。

If Len(strPrint) = 0 Then
       Response.Clear
       Response.End
End If

7.2.2 指令碼運行期錯誤
       使用一個不存在的函數,或者破壞了指令碼語言使用的規則,會出現指令碼運行期錯誤。許多錯誤是語法錯誤(本章前面討論過的),但是許多錯誤是由於所賦的值和函數參數的要求不一致引起的。例如,用一個表單收集來自使用者的日期,並存入資料庫中,或者用其他方式進行處理。為了確定日期是有效,在把資料插入資料庫之前使用CDate函數:
       <%
       strDate = Request.Form("TheDate")
       datDate = CDate(strDate)
       …
       如果使用者在填表時出現了差錯,程式便會產生一個指令碼錯誤,如圖7-12所示:

       查看錯誤資訊,可以發現錯誤是由執行程式代碼的指令碼引擎產生的。錯誤號碼用十六進位顯示出來,它是由VBScript錯誤號碼和十六進位數0x800A0000相加得到的(見第4章),上例中VBScript錯誤號碼是十六進位0xD,或者十進位數的13。
       大多數微軟技術(包括ASP)返回的錯誤號碼是由8位十六進位數組成的。第一位字元總是8,表明這個狀態資訊是伺服器錯誤資訊。後面跟著2位0,然後是服務代碼。對VBScript和JScript錯誤,服務代碼總是“A”,最後4位字元是用十六進位數表示的錯誤號碼。
       如果查看一下VBScript文檔,你會發現13號錯誤是“Type Mismatch”錯誤。當然,我們從ASP錯誤頁中顯示的錯誤描述中已經知道了這一點。然而,在本章後面我們將要看到,在錯誤處理技術中,得到錯誤號碼是非常有用的。
       注意,在錯誤資訊顯示視窗中,顯示的是伺服器對錯誤的反饋資訊。HTTP狀態碼為500.100,屬於“Internal Server Error”。在第4章,討論ASP定製錯誤網頁的工作方式時,我們發現這種錯誤常常因為載入了錯誤網頁。本章後面,將會看到在網頁中如何處理這些錯誤。

7.2.3 ASP和SSI的運行期錯誤
       指令碼錯誤是由正在使用的指令碼引擎發現的,然而ASP DLL和SSI DLL也能發現指令碼錯誤,儘管它們與使用的指令碼引擎無關。典型的SSI例子是在#include指令中給檔案一個錯誤的名字或路徑。錯誤是由SSI DLL或ASP發現的,而不是由指令碼引擎發現。可看到此時錯誤類型是“Active Server Pages”,ASP內部錯誤碼是“ASP 0126”,如圖7-13所示,然而在這種情況下,錯誤號碼是4005,指出了這是一種SSI DLL(ssinc.dll)定義的特殊錯誤。

       ASP錯誤碼總覽
       對於在ASP DLL中造成失敗的錯誤,表7-1是返回的錯誤碼。當這類錯誤發生時,你可以在ASPError對象的ASPCode屬性中找到這些錯誤碼。
表7-1  ASP錯誤碼
錯誤碼
錯誤訊息和擴充資訊

ASP0100
Out of Memory(記憶體溢出)

ASP0101
Unexpected error(函數返回exception_name)

ASP0102
Expecting string input(期待字串輸入)

ASP0103
Expecting numeric input(期待數字輸入)

ASP0104
Operating not allowed(操作不允許)

ASP0105
Index out of range(數組下標溢出)

ASP0106
Type Mismatch(資料類型不匹配)

ASP0107
Stack Overflow(處理的資料量超過了允許的範圍)

ASP0115
Unexpected error(出現在外部對象中的可捕獲的錯誤exception_name,指令碼不能繼續運行)

ASP0177
Server.CreateObject Falied(無效的ProgID)

ASP0190
Unexpected error(當釋放外部對象時,出現的可捕獲的錯誤)

ASP0191
Unexpected error(當外部對象的OnStartPage方法中出現的可捕獲的錯誤)

ASP0192
Unexpected error(在外部對象的OnEndPage方法中出現的可捕獲的錯誤)

ASP0193
OnStartPage Failed(在外部對象OnStartPage方法中出現錯誤)

ASP0194
OnEndPage Failed(在外部對象的OnEndPage方法中出現錯誤)

ASP0240
Script Engine Exception(指令碼引擎從object_name拋出異常exception_name)

ASP0241
CreateObject Exception(object_name的CreateObject方法所導致的異常exception_name)

ASP0242
Query OnStartPage Interface Exception(查詢對象object_name的OnStartPage或OnEndPage方法所導致的異常exception_name)

       ASP錯誤通常僅當組件有問題或伺服器本身有問題時才出現。最常見是使用Server.CreateObject時的ASP 0177錯誤和嚴重的ASP 0115錯誤。ASP 0115錯誤通常表示組件程式碼中發生的錯誤,而ASP 0177錯誤通常是由不能正確安裝組件引起的或者由我們指定的ProgID字串的錯誤引起的。
7.2.4 用戶端指令碼錯誤
       到目前為止,我們已瞭解了來自ASP的錯誤。然而ASP也經常用於建立包含用戶端指令碼的網頁。如果包含用戶端代碼的<SCRIPT>元素沒有被設定成RUNAT="SERVER"屬性,ASP將不考慮伺服器,而把網頁資訊不加改變地傳送到用戶端。
       因此,如果開啟了一個ASP網頁,並且顯示的是一個瀏覽器錯誤對話方塊,就不應該在伺服器端尋找ASP程式碼的錯誤。瀏覽器看不到ASP程式碼,所以不能識別任何錯誤,如果有一個對話方塊出現在用戶端,那麼在用戶端代碼中必定有一個錯誤。
1.  語法錯誤
如果在網頁中的用戶端程式代碼有語法錯誤的話,當指令碼下載到用戶端,瀏覽器便會出現相應的錯誤。儘管網頁中內容仍可正常載入(除非由這些用戶端指令碼代碼動態裝入),但網頁停止執行。使用者將看到一個包含錯誤細節的對話方塊,或者是一個指示網頁包含錯誤的狀態條訊息。
現代瀏覽器趨向於隱藏網頁指令碼錯誤的細節,而僅在狀態條上顯示一個小的錯誤表徵圖。在IE 4.0和IE 5.0中,正常的錯誤對話方塊可以通過Internet Options對話方塊的Advanced頁進行設定來啟用,如圖7-14所示:

處理指令碼程式碼中的用戶端錯誤和在伺服器端相似,並且通常會更容易些,因為經常可以直接從伺服器目錄中通過雙擊來下載網頁。一般不需要通過Web伺服器和HTTP獲得網頁來觀察瀏覽器中的結果,其中的唯一不同是一些伺服器互動由用戶端指令碼來完成,如使用RDS的資料繫結或者動態裝入。
2.  運行期或語義錯誤
在用戶端指令碼中,通常可能會遇到語法錯誤,也會經常遇到運行期或語義錯誤。事實上,在用戶端,這種現象是很普遍的。因為在用戶端不能像伺服器端那樣對指令碼的環境進行控制,不能肯定使用者在他們的機器上正運行什麼,實際上在伺服器上僅能從一些組件如Browser Capabilities中得到大概情況。
所以,使用用戶端對象或特殊版本的指令碼語言和屬性的指令碼程式很可能不能正常工作。儘管如此,處理用戶端錯誤和處理伺服器端錯誤是差不多的。
3.  在伺服器上建立的用戶端程式代碼
在錯誤發生時,作為“用戶端對話方塊對應於ASP錯誤頁面”規則(關於出錯的地方)的一個特別的例外是,使用ASP程式碼在伺服器上動態地建立用戶端程式代碼。例如,可能想在ASP中進行求值運算,然後把資料傳給運行在用戶端的指令碼代碼,可能最容易的方法是把資料作為一個變數插入指令碼代碼中:
<%
' get the name of our server from the ServerVariables collection
strServerNameInASP = Request.ServerVariables("SERVER_NAME")
%>

<SCRIPT LANGUAGE="JScript" RUNAT="CLIENT">
<!-- hide code from older browsers
var strServerName = "<% = strServerNameInASP %>";

alert('Server name is: ' + strServerName);

// stop hiding code
-->
</SCRIPT>
在用戶端,在ASP處理這個頁面之後,將得到的是:
<SCRIPT LANGUAGE="JScript" RUNAT="CLIENT">
<!-- hide code from older browsers
var strServerName = "WROXBOX";

alert('Server name is: ' + strServerName);

// stop hiding code
-->
</SCRIPT>
可以忽略RUNAT="CLIENT"屬性,但是加上這一項可以使得在查看運行代碼的ASP網頁時更加清楚。
這樣,如果在某個位置想把伺服器端資料庫中的資料加入到一個用戶端數組中,可以採用下面的程式實現:
<SCRIPT LANGUAGE="JScript" RUNAT="CLIENT">
<!-- hide code from older browsers
var arrBooks = new Array(10)             //highest available index will be

<% ' start of ASP processing
intIndex = 0
Do While { not at the end of some recordset }
              strTitle = { get title from database record }
              Response.Write "arrBooks[" & CInt(intIndex) & "] = '" _
                                   & strTitle & "'; " & vbCrlf
              intIndex = intIndex +1
              { move to next record in database }
Loop

do something here on the client with the array of book titles

// stop hiding code
-->
</SCRIPT>
這段伺服器端ASP程式碼產生的用戶端代碼,在用戶端運行時建立書名標題數組。同時產生的用戶端指令碼錯誤出現在瀏覽器的錯誤對話方塊中。錯誤的原因是以arrBooks命名的數組是由JavaScript代碼運行在用戶端時建立的,僅能接受9個書名;而伺服器端代碼能很可能產生多於9個的書名,具體多少由來源資料庫中的記錄數來決定。這相當於如下用戶端代碼:
<SCRIPT LANGUAGE="JScript" RUNAT="CLIENT">
<!-- hide code from older browsers
var arrBooks = new Array(10)             //highest available index will be
arrBooks[0] = 'Instant JavaScript';
arrBooks[1] = 'Professional ASP 3.0 Programming';
arrBooks[2] = 'ADO 2.5 Programmers Reference';

etc

arrBooks[9] = 'ASP Techniques for Webmasters';
arrBooks[10] = 'ASP Programmers Reference';          // <- client-side error occurs here
arrBooks[11] = 'ADSI CDO Programming';
arrBooks[12] = 'Professional MTS and MSMQ Programming';

do something here on the client with the array of book titles

// stop hiding code
-->
</SCRIPT>
這個頁面只有經過修正之後才能正常工作,可以通過增加數組大小,也可以通過控制來自資料庫的記錄數使其正常工作。




相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。