?? pl004.asp
字號:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE>程式設計基礎講座(四) ─ 向 bug 宣戰, 程式中最容易潛藏 BUG 的地方</TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.01Gold (Win95; I) [Netscape]">
</HEAD>
<BODY BACKGROUND="back01.jpg">
<H3><FONT COLOR="#008000">程式設計基礎講座(四)</FONT></H3>
<H2 ALIGN=CENTER><FONT COLOR="#0000FF"><FONT SIZE=+3>向 bug 宣戰─<BR>
程式中最容易潛藏 BUG 的地方</FONT></FONT></H2>
<P>
<HR WIDTH="100%"><A NAME="S0"></A><B><FONT COLOR="#0000FF"><FONT SIZE=+2>本文大綱</FONT></FONT></B></P>
<UL>
<TABLE WIDTH="80%" >
<TR VALIGN=TOP>
<TD VALIGN=TOP><A HREF="#s1">數學運算式</A></TD>
<TD><A HREF="#s2">程式轉彎處</A></TD>
<TD><A HREF="#s3">變數</A></TD>
</TR>
</TABLE>
</UL>
<CENTER><TABLE WIDTH="95%" >
<TR>
<TD>蟑 螂 是 生 命 力 很 強 的 動 物 , 大 概 有 人 的 地 方 就 有 它 ,
雖 然 人 類 發 明 了 許 多 殺 蟑 的 方 法 , 但 蟑 螂 還 是 沒 有 因 此
絕 跡 ; 電 腦 的 bug 很 像 蟑 螂 , 它 總 是 悄 悄 地 躲 進 我 們 所 開
發 的 程 式 中 , 雖 然 大 部 份 的 軟 體 開 發 工 具 都 有 殺 蟲 劑 (debugger),
但 bug 也 沒 有 因 此 絕 跡 。
<P>我 有 一 位 很 強 壯 的 同 事 卻 很 怕 蟑 螂 , 只 要 看 到 蟑 螂 ,
他 一 定 要 翻 箱 倒 柜 把 它 找 出 來 , 否 則 便 無 法 入 睡 , 這 讓
我 聯 想 到 是 否 有 人 為 了 一 個 bug 而 翻 遍 所 有 的 程 式 ? 對 於
小 程 式 來 說 , 這 也 許 不 是 太 難 的 事 情 , 但 對 於 大 型 程 式
, 這 卻 是 不 實 際 的 , 就 像 您 要 在 幾 十 層 的 大 樓 中 搜 索 一
支 蟑 螂 一 樣 。 </P>
<P>我 想 應 該 先 從 蟑 螂 最 常 出 沒 的 地 方 開 始 , 甚 至 在 這 些
地 方 擺 放 殺 蟑 劑 , 同 樣 的 , 在 程 式 中 也 有 bug 比 較 容 易 躲
藏 的 地 方 , 我 們 首 先 要 確 定 bug 是 否 會 躲 藏 在 這 些 地 方 ,
并 且 埋 設 一 些 檢 查 的 關 卡 , 只 要 bug 出 現 就 能 顯 現 警 告 訊
息 。 </P>
<P>蟑 螂 的 多 寡 與 家 具 的 選 擇 有 極 大 的 關 系 , 同 樣 的 , bug
的 多 寡 與 開 發 程 式 的 語 言 也 有 極 大 的 關 系 , 而 在 眾 多 流
通 廣 泛 的 程 式 語 言 中 , 又 以 C 語 言 為 bug 的 最 愛 , 本 期 探
討 一 般 程 式 語 言 容 易 潛 藏 bug 的 地 方 , 或 多 或 少 會 以 C 語
言 為 例 , 不 過 較 完 整 的 整 理 及 討 論 則 留 待 以 後 。 </P>
</TD>
</TR>
</TABLE></CENTER>
<H2><A NAME="s1"></A><FONT COLOR="#0000FF">數學運算式</FONT></H2>
<UL>
<P>如 果 客 戶 的 利 息 算 錯 , 如 果 飛 彈 的 彈 道 算 錯 , 如 果 …
, 利 用 電 腦 來 代 替 人 類 作 運 算 , 原 本 在 取 其 既 迅 速 又 準
確 的 特 性 , 為 什 麼 還 會 有 錯 呢 ? </P>
</UL>
<H3><B><U><FONT COLOR="#000080">錯 誤 類 型 之 一 : 溢 位</FONT></U> </B></H3>
<UL>
<P>對 人 類 來 說 , 「 整 」 的 范 圍 是 從 -∞ 到 +∞ , 對 電 腦 程
式 語 言 來 說 , 「 數 」 卻 有 固 定 的 范 圍 , 因 此 只 要 含 有 +
- × ÷ 等 運 算 符 號 ( operator) 的 運 算 式 , 其 運 算 結 果 都
可 能 超 過 電 腦 程 式 語 言 所 預 設 的 范 圍 。 舉 個 例 子 來 說 :
以 16 位 元 為 整 數 范 圍 ( -32768 到 32767) 的 運 算 中 , 當 a >=
128時 , 運 算 式 「 a * 256」 的 結 果 ( >=32768) 即 超 出 整 數
的 范 圍 , 這 就 是 所 謂 的 「 溢 位 」 ( overflow) 。 </P>
<P>溢 位 的 預 防 別 無 他 法 , 只 有 檢 視 每 一 個 運 算 式 , 并 且
確 定 運 算 子 ( operand ) 的 可 能 值 不 會 使 運 算 式 造 成 溢 位
, 舉 例 來 說 , 您 可 以 在 a * 256 的 運 算 式 前 面 加 上 一 段 邏
輯 判 斷 , 例 如 : </P>
<UL>
<ADDRESS><FONT COLOR="#000080">If -128 <= a And a < 128 Then </FONT></ADDRESS>
<UL>
<ADDRESS><FONT COLOR="#000080">x = a * 256 </FONT></ADDRESS>
</UL>
<ADDRESS><FONT COLOR="#000080">Else </FONT></ADDRESS>
<UL>
<ADDRESS><FONT COLOR="#000080">' 停 止 運 算 </FONT></ADDRESS>
</UL>
<ADDRESS><FONT COLOR="#000080">End If</FONT></ADDRESS>
</UL>
<P>但 對 於 比 較 復 雜 的 運 算 式 , 這 種 作 法 并 不 實 際 , 舉 例
來 說 , 我 們 很 難 寫 出 運 算 式 「 a*a + b*10 + c」 是 否 溢 位 的
判 斷 式 , 解 決 這 個 問 題 較 好 的 方 法 是 利 用 程 式 語 言 「 例
外 處 理 」 的 能 力 , 例 如 Visual Basic 就 有 「 On Error ...」 ( 當
發 生 錯 誤 時 , 就 … ) 的 語 法 , 以 下 是 一 個 實 例 : </P>
</UL>
<UL>
<UL>
<ADDRESS><FONT COLOR="#000080">On Error GoTo ErrorHandler</FONT></ADDRESS>
<UL>
<ADDRESS><FONT COLOR="#000080">x = a*a + b*10 + c ...</FONT></ADDRESS>
</UL>
<ADDRESS><FONT COLOR="#000080">ErrorHandler:</FONT></ADDRESS>
<ADDRESS><FONT COLOR="#000080">' 若 發 生 「 溢 位 」 的 錯 誤 時 , 變
數 Err 將 等 於 6 </FONT></ADDRESS>
<ADDRESS><FONT COLOR="#000080">If Err = 6 Then ... </FONT></ADDRESS>
<UL>
<ADDRESS><FONT COLOR="#000080">' 告 訴 使 用 者 發 生 溢 位 了 </FONT></ADDRESS>
<ADDRESS><FONT COLOR="#000080">Exit Sub </FONT></ADDRESS>
</UL>
<ADDRESS><FONT COLOR="#000080">Else </FONT></ADDRESS>
<UL>
<ADDRESS><FONT COLOR="#000080">... </FONT></ADDRESS>
</UL>
<ADDRESS><FONT COLOR="#000080">End If</FONT></ADDRESS>
</UL>
<P>不 過 并 不 是 所 有 的 程 式 語 言 都 具 有 「 例 外 處 理 」 的 機
制 , 以 C 語 言 為 例 , 發 生 溢 位 時 , 并 不 會 產 生 溢 位 的 錯
誤 , 只 是 簡 單 地 把 溢 位 的 部 份 去 掉 , 表 面 看 起 來 程 式 還
能 夠 正 常 地 執 行 , 但 實 際 上 執 行 的 結 果 卻 是 錯 誤 的 , 這
是 使 用 C 語 言 應 該 特 別 注 意 的 地 方 。 </P>
</UL>
<H3><B><U><FONT COLOR="#000080">錯 誤 類 型 之 二 : 浮 點 數 的 不 準
確 性 </FONT></U></B></H3>
<UL>
<P>10 + 0.1 等 於 10.1, 這 麼 簡 單 的 算 數 小 學 生 都 會 , 以 下 是
以 Visual Basic 所 做 的 實 驗 : </P>
<UL>
<ADDRESS><FONT COLOR="#000080">x = 10.0</FONT></ADDRESS>
<ADDRESS><FONT COLOR="#000080">While x < 20.0</FONT></ADDRESS>
<UL>
<ADDRESS><FONT COLOR="#000080">x = x + 0.1</FONT></ADDRESS>
<ADDRESS><FONT COLOR="#000080">Print x</FONT></ADDRESS>
</UL>
<ADDRESS><FONT COLOR="#000080">Wend</FONT></ADDRESS>
</UL>
<P>結 果 列 印 出 來 的 值 自 11.3 以 後 就 不 完 全 正 確 了 : </P>
<UL>
<ADDRESS><FONT COLOR="#000080">...</FONT></ADDRESS>
<ADDRESS><FONT COLOR="#000080">11.1</FONT></ADDRESS>
<ADDRESS><FONT COLOR="#000080">11.2</FONT></ADDRESS>
<ADDRESS><FONT COLOR="#000080">11.3</FONT></ADDRESS>
<ADDRESS><FONT COLOR="#000080">11.40001 ← 開 始 產 生 偏 差 </FONT></ADDRESS>
<ADDRESS><FONT COLOR="#000080">11.50001</FONT></ADDRESS>
<ADDRESS><FONT COLOR="#000080">11.60001</FONT></ADDRESS>
<ADDRESS><FONT COLOR="#000080">...</FONT></ADDRESS>
</UL>
<P>這 并 非 Visual Basic 的 錯 誤 , 問 題 的 原 因 是 電 腦 以 有 限 的
位 數 來 表 達 無 限 的 數 值 范 圍 所 產 生 的 誤 差 , 雖 然 這 些 誤
差 通 常 都 小 得 可 以 忽 略 它 的 存 在 , 但 仍 有 幾 件 事 情 必 須
加 以 注 意 : </P>
<UL>
<P>·當 我 們 需 要 更 精 確 的 浮 點 計 算 值 時 , 先 確 定 程 式 語
言 能 否 滿 足 需 求 。 </P>
<P>· 同 樣 的 浮 點 運 算 式 在 不 同 機 器 、 或 不 同 的 程 式 語 言
, 可 能 因 為 其 表 達 浮 點 數 的 方 法 不 同 , 而 造 成 計 算 出 來
的 結 果 也 不 同 。 </P>
<P>· 在 邏 輯 判 斷 式 中 , 盡 量 不 要 判 斷 兩 個 浮 點 數 是 否 相
等 , 例 如 以 下 的 回 圈 極 可 能 無 法 結 束 : </P>
<UL>
<ADDRESS><FONT COLOR="#000080">x = 10.0</FONT></ADDRESS>
<ADDRESS><FONT COLOR="#000080">While x <> 20.0</FONT></ADDRESS>
<ADDRESS><FONT COLOR="#000080">' 當 x 等 於 20.0 時 跳 出 回 圈 </FONT></ADDRESS>
<UL>
<ADDRESS><FONT COLOR="#000080">...</FONT></ADDRESS>
<ADDRESS><FONT COLOR="#000080">x = x + 0.1</FONT></ADDRESS>
</UL>
<ADDRESS><FONT COLOR="#000080">Wend</FONT></ADDRESS>
</UL>
</UL>
<P>其 原 因 是 x 雖 然 會 達 到 20.0 的 及 近 似 值 ( 以 Visual Basic
為 例 , 其 值 會 達 到 20.00004) , 但 終 究 不 等 於 20.0, 以 致 無
法 跳 出 回 圈 。 </P>
</UL>
<P><B><U><FONT COLOR="#000080"><FONT SIZE=+1>錯 誤 類 型 之 三 : 除 以
0</FONT></FONT></U></B></P>
<UL>
<P>當 然 沒 有 人 會 笨 到 寫 出 (x / 0) 這 樣 的 運 算 式 , 但 類 似
(x / y) 的 運 算 式 相 信 大 家 都 寫 過 , 因 此 遇 有 相 除 的 運 算
式 時 , 不 妨 先 檢 查 除 數 y 是 否 為 0 的 判 斷 式 , 例 如 : </P>
<UL>
<ADDRESS>If y <> 0 Then</ADDRESS>
<UL>
<ADDRESS>z = x / y</ADDRESS>
</UL>
<ADDRESS>Else</ADDRESS>
<UL>
<ADDRESS>...</ADDRESS>
</UL>
<ADDRESS>Endif </ADDRESS>
</UL>
</UL>
<P><B><U><FONT COLOR="#000080"><FONT SIZE=+1>錯 誤 類 型 之 四 : 弄 錯
運 算 符 號 的 優 先 順 序 </FONT></FONT></U></B></P>
<UL>
<P>數 學 運 算 式 中 , 先 × ÷ 後 + - , 相 信 大 家 都 記 得 清 清
楚 楚 , 不 過 一 個 夠 格 的 程 式 語 言 , 其 所 包 含 之 運 算 功 能
應 該 不 只 這 些 , 可 能 還 包 括 冪 次 方 、 求 馀 數 、 AND、 OR、
XOR 等 , 而 各 種 程 式 語 言 在 運 算 符 號 的 優 先 順 序 定 義 上 并
不 盡 相 同 , 舉 例 來 說 , 以 下 的 運 算 式 在 BASIC 及 C 語 言 的
運 算 結 果 并 不 相 同 : ( 注 : Mod 及 % 分 別 是 BASIC 及 C 語 言
的 求 馀 數 ) </P>
<UL>
<ADDRESS><FONT COLOR="#0000FF">BASIC: 10 Mod 6 / 2 結 果 等 於 1</FONT></ADDRESS>
<ADDRESS><FONT COLOR="#0000FF">C : 10 % 6 / 2 結 果 等 於 2</FONT></ADDRESS>
</UL>
<P>這 兩 種 運 算 式 的 結 果 之 所 以 不 同 , 問 題 就 出 在 運 算 符
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -