国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

隱藏的數據炸彈可能是導致不正常崩潰的罪魁禍首

2019-11-18 15:18:47
字體:
來源:轉載
供稿:網友

  內容:
百萬分之一
破壞者數據錯誤模式
語法原因
語義原因
治療和預防措施
結論
參考資料
關于作者
對本文的評價

隱藏的數據炸彈可能是導致不正常崩潰的罪魁禍首
Eric E. Allen(eallen@cyc.com)
java 開發人員帶頭人,Cycorp, Inc.

程序由于損壞的數據而崩潰時,破壞者可能難以捉摸。一個程序經常在處理自身內部的數據的過程中就會崩潰,這甚至會發生在程序已經不出錯誤地運行了很長一段時間以后。本文將討論一種錯誤模式(它可能就是引起這種崩潰的罪魁禍首),還有它為什么會存在,以及在它出現之前和之后的幾種消除它的方法。
百萬分之一
作為一個勤奮的開發人員,您已經為幾個需要更好地訪問復雜的大量數據存儲的客戶安裝了一個應用程序,它編寫良好,而且經過了充分測試。

對每個客戶,現場測試階段都暢通無阻地通過了。您在去銀行的路上,心里極少考慮這六個月來的軟件審查,這時您的傳呼機響了起來。您的一個客戶在使用您的軟件運行一個報表時,系統崩潰了。

您趕到出事地點,運行了一個隨機測試。工作良好。您運行另一個。沒出現問題。您又運行了數百個測試。還是沒有問題。您又檢查了持續六個月運行這個應用程序的其它客戶。沒有投訴。

您重復運行那個引起問題的報表。崩潰!怎么回事?

快速跟蹤代碼
清單 1. 樣本,外部源文本文件
這種數據由程序讀取。可以從文件、鍵盤、麥克風、網絡或者電子手套進行輸入。
清單 2. 使用 StreamTokenizer 插入域和區域字符串
這種插入兩個 String 的方法是否行得通取決于從文本文件獲取 String 的方式。

清單 3. 數據破壞者
這個數據錯誤的示例可以引起程序崩潰。

破壞者數據錯誤模式
許多程序需要頻繁訪問和處理內部儲存的數據來執行各種復雜的任務。這種數據可以從內存中的大型結構、數據庫或網絡上檢索得到。

這類程序非常輕易遭受損壞的內部數據引起的崩潰。我稱這種錯誤模式為破壞者數據模式,是因為這種數據可以無限期地存在于系統中(很象冷戰中的潛伏間諜一樣),不引發任何問題,直到訪問一段特定的數據時,損壞的數據才象炸彈一樣爆炸。

語法原因
假定我們有一個 JDBC 應用程序,它存儲了一個名為 Mapping 的數據庫表,該表將 String 的名稱映射到一系列元素的集合。(請參閱參考資料,以獲取關于 JDBC API 的更多信息。)每個集合中的每個元素都引用另一個表中的一個要害字(該表名為 PRoperties,包含這些元素的不同已知屬性)。

這樣說吧,Mapping 和 Properties 表最初都是從一個文本文件中讀取的,這個文本文件由外部源(外部意為不是內部產生的任意數據源)發展而來,而在外部源中,每行都以一個名稱開頭,后面跟著對應集合的表達,如下所示:

清單 1. 樣本,外部源文本文件

In the Mapping file:

apples {macintosh, gala, golden-delicious}

trees {elm, beech, maple, pine, birch}

rocks {quartz, limestone, marble, diamond}

...

In the Properties file:

macintosh {color: red, taste: sour}

gala {color: red, taste: sweet}

diamond {color: clear, rigidity: hard, value: high}

...

可以對 Mapping 和 Properties 表條目進行語法分析并將其傳遞到一個方法中,此方法會把這些條目插入到一個數據庫中。但這種方法存在潛在的缺陷。例如,假定我們已經編寫了一個處理 JDBC 兼容數據庫的類。遵照 JDBC API,我們可以定義一個 PreparedStatement 對象并使用它把信息傳遞到數據庫中,如下所示:

清單 2. 使用 StreamTokenizer 插入域和區域字符串

...

PreparedStatement insertionStmt =

con.prepareStatement("INSERT INTO MAPPING VALUES(?,?)");

...

public void insertEntry(String domain, String range)

throws SQLException {

insertionStatement.setString(1, domain);

insertionStatement.setString(2, range);

insertionStatement.executeUpdate();

}

以這種方式插入兩個 String 合適與否取決于從文本文件中獲取 String 的方式。例如,假定一個簡單的正則表達式匹配工具被用來將每一行拆分成兩個 String:

一個 String 包含第一個 String 之前的全部字符。
一個 String 包含第一個 String 之后的全部字符。
這種對文本文件進行的基本的語法分析不會捕捉數據的較小損壞。例如,假如其中的一行是如下的形式:

清單 3. 數據破壞者

trees {elm, beech, maple, pine birch}

“pine”和“birch”之間的逗號漏掉了。這樣的錯誤很輕易由生成文件的工具的錯誤或手工編輯文件而造成。

無論如何,數據都會以損壞的形式進入數據庫,靜靜地等待被訪問。假如用于訪問數據的方法要求用逗號和空格來分隔條目,在讀取這個條目的時候就會導致崩潰。

假如程序只是簡單地使用逗號來區分集合中的元素,更加嚴重的錯誤都可能發生。系統可能將“pine birch”解釋為一個單獨的樹類型(數據的單個條目),并將這個錯誤進一步傳播到計算中去。

語義原因
我們的示例是一個違反了數據的一個簡單的語法特征演示。當然,這不是可能損壞數據的唯一途徑。

語義級別上的限定因素也可能被破壞。在我們的示例中,Mapping 表中數據的一種要求是,每個集合中的每個元素都是 Properties 表中的一個域條目。假如這種不變量被破壞,程序就會在試圖讀取一個在 Properties 表中并不存在的元素時失敗,導致異常被拋出。

在本文中,我使用數據庫條目作為示例,但是破壞者數據錯誤會以各種方式出現 ? 與數據輸入的方式一樣多。當程序讀取數據時,不管它是從文件、鍵盤、麥克風、網絡還是電子手套讀取,破壞者數據錯誤都有可能存在。

治療和預防措施
最好的防御破壞者數據錯誤的方法是編譯器和解釋器開發人員普遍采用的那種方法。由于輸入到這些程序的數據是如此復雜,開發人員別無它法,只有在第一次讀取輸入內容的時候就執行盡可能徹底的完整性檢查,而不是在以后訪問的時候再進行檢查。

語法分析作為消除錯誤的方法
實際上,對輸入內容進行語法分析的方法恰好是消除大量這些錯誤的途徑。不幸的是,很多程序員(他們從來不會考慮編寫沒有語法分析器的編譯器)沒有能夠為較簡單的數據編寫足夠的語法分析方法。較簡單的數據的語法分析當然要輕易一點,但是這并不能成為根本不對它進行語法分析的借口。

任何讀取數據的程序 ? 不管有多簡單 ? 都應該對數據進行語法分析。究竟,這種程序在它的有效輸入的集合所定義的“語言”上可以被看作是一個編譯器(或者解釋器)。

從經歷過的人那里吸取一點經驗吧。我年輕時比較魯莽,犯了個錯誤 ? 處理數據的時候沒有作適當的語法分析,然后我就遭受了那樣的后果 ? 猖獗的破壞者。我可不推薦這種經驗。

類型檢查作為消除錯誤的方法
編譯器為許多語言(當然包括 Java 語言)所作的檢查的另一種普遍形式是類型檢查。類型檢查是程序完整性上的語義級別檢查的一個示例。

假如類型系統是健壯的(就象 Java 類型系統一樣),這種完整性檢查確實可以保證很多錯誤永遠不會在運行時產生。象語法分析一樣,編譯器編寫者的這個示例可以應用于其它經常在其輸入數據上規定語義級別不變量的程序。這些不變量通常不是明確的,但可以通過進行對應的檢查來把它們變成明確的。

反復操作作為消除錯誤的方法
當然,假如您懷疑這種錯誤模式的出現與已經讀入并存儲的數據有關,反復操作數據也是明智的:訪問在實際配置的應用程序中可能要操作的每個數據,保證一切都象期望的那樣工作。通過這種方法,您也能夠修正簡單的錯誤。

關于消除錯誤方法的一個告誡
我的意思當然不是暗示執行足夠的檢查來消除程序中的所有破壞者數據總是可行的。假如真是那樣,就不會有引起錯誤模式的潛在問題了。

一個破壞者在開始帶來災難之前為什么會無法覺察是有很多原因的:

執行所有檢查必需的數據直到破壞者數據已經存儲了以后才可用。
整套的限定元素甚至是無法計算的(就象編譯器和解釋器的情況一樣)。
限定元素可以計算,但是程序無法訪問檢查它們所需要的資源。
在這些情況下,我們最好是盡量消除可能的破壞者形式。

結論
下面是破壞者數據錯誤模式的總結:

模式:破壞者數據
癥狀:一個存儲和處理復雜的輸入數據的程序在執行任務時意外地崩潰,而這個任務和其它沒有產生任何問題的任務很相似。
起因:一些內部數據被損壞,可能是語法上的損壞,也可能是語義上的。
治療和預防措施:對輸入數據盡量多地執行完整性檢查,而且要盡量早執行。對于已經損壞的持久數據,研究它并檢查其完整性。
消除數據破壞者的黃金法則:任何讀取數據的程序都應該對數據進行語法分析。愿您能順利消除這些錯誤!

參考資料

參與本文的討論論壇。
要了解有關 JDBC 的更多信息,請查看關于本主題的 Java 數據庫連接教程(developerWorks,2000 年 4 月)。
學習 Java 調試教程(developerWorks,2001 年 2 月)來獲得一般調試技巧的幫助。
訪問 Enhydra 主頁來下載 Instant DB,一個免費的 JDBC 驅動程序。盡管要讓它適用于大型數據庫還需要一些技巧,但用它處理中等大小的表還是不錯的。
盡管遭受非議,正則表達式讀取器還是很強大的工具。看看 OroMatcher,一個 Java 語言的正則表達式匹配器,它讀取 Perl 類型的正則表達式。
Java 語言有很多類似于 Lex 和 Yacc 的東西(標準語法分析器工具),請看一下 ANTLR 的一個這樣的例子。
閱讀 Eric 關于錯誤模式的 完整系列。

關于作者
Eric Allen 在 Cornell 大學獲得計算機科學和數學的學士學位。他目前是 Cycorp 公司的 Java 軟件開發人員帶頭人,還是 Rice 大學的編程語言小組的兼職碩士生。他的研究涉及在源程序和字節碼層次上的正規語義模型和 Java 語言擴展的開發。目前,他正在為 NextGen 編程語言實現一種從源代碼到字節碼的編譯器,這也是 Java 語言的泛型運行時類型的一種擴展。請通過 eallen@cyc.com 與 Eric 聯系。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 宣恩县| 女性| 资溪县| 大同市| 阿坝县| 鞍山市| 咸丰县| 金川县| 莱芜市| 光山县| 金山区| 湘西| 彭山县| 鄢陵县| 东城区| 兴义市| 平泉县| 随州市| 搜索| 高安市| 德钦县| 甘洛县| 鄯善县| 广平县| 河北省| 南皮县| 甘孜| 台东县| 什邡市| 桂东县| 勃利县| 南涧| 乌苏市| 荔浦县| 资溪县| 泸州市| 西宁市| 广河县| 普安县| 江永县| 蒙阴县|