• 沒有找到結果。

1.1. 研究動機

軟體發展過程中,由於團隊成員的更迭,使得舊成員無法再維護其先前所負責的部 份,後繼者僅能依循之前所留下之文件及程式碼。在大部份的情形下,程式設計者主要 的工作是使程式動作能符合需求,而非文件撰寫,在時間與資源的壓力下,文件撰寫常 成為犧牲的部份,因此在這種情況下,文件的品質是無法確定的;而在程式的了解上,

我們僅能由檢視程式碼或再加上 Cross-Reference[1]工具的協助,然而在一個大型專案 中,程式元件之間的互動可能是相當複雜的,使用這些靜態檢視或分析的工具僅能有部 份協助,在程式語意的部份需要更進一步的工具來告知。 我們將為上述問題提出解決 方法:當文件缺乏而程式碼複雜的情形下,新進者如何更快地參與程式的開發。

經由這套方法的幫助,可進一步地解釋部份軟體工程中的現象。這項工作有益於以 下的情況:在開放原始碼專案中,有時需取出特定檔案、與其發展歷程中的狀態,做一 分支開發或其它工作;或整合前面的發展時,特別是之前的程式碼並非由自己所撰寫,

必須判斷之前的修改意義,才能進一步地整合成完整的程式。

當程式整合之後,開發者需判斷程式的非預期行為,但每個專案都有其特有之問 題,這些問題的發現或解決有賴於該專案團隊的經驗。在舊成員離開後,這種經驗可能 無法傳承。透過我們的方法,期望將這些經驗以某種自動化的程度呈現出來。

當程式設計人員因為種種因素-如許久未參與或更動該部份之開發,亦或是新加入 者-無法獲得該經驗時,首先可能是程式開發產生阻礙,甚至是開發者在一知半解的情 形之下撰寫或修改該部份,可能會導致違反系統內隱含的規則(implicit rule),此類規則為 程式正常執行的條件,因此在某些情形下違反該規則之設計會導致程式出錯,嚴重者可 能會導致系統毀損。因此,在此我們前段所得之結果為基礎,針對程式中可能出錯的部 份提出建議,供程式撰寫者參考。

1.2. 問題描述

在 Imperative language paradigm(如 C, Pascal 等語言)之程式開發中,二個或二個以 上的函式(function call)有時會共同出現於程式中,此種情形在出現次數達到一閥值後,

便可將此共同出現之情形稱為 pattern。目前現有的論文大多注重於單純函式呼叫的共同 出現性[2-5],而較少關注到函式所使用之參數或回傳值。

在此我們發現到,函式使用常伴隨著暫態的使用,此種暫態有時以區域或全域變數 的形式出現。在此以一段 C 語言程式說明:

{…

var_DEP = foo(var_ARG);

buk(var_DEP);

…}

其中 var_DEP 以及 var_ARG 皆為上文所稱之暫態,而 foo 及 buk 各為函式呼叫。

函式 foo()所回傳的值—var_DEP 為函式 buk()所用,在出現頻率夠高的情形下,我們 可以將此種使用情形稱為 pattern。在本篇論文中,我們提出演算法以找出此類 Pattern,

用以補[2-5]在 dataflow 分析上之不足。

1.2.1. 以 OPENSSH 為例

我們取 OpenSSH (版本為 4.3p2),位於 ssh.c 內的 control_client()函式中一段程式做 為說明:

圖 1 OpenSSH 程式內容舉例

以上圖為例,此程式使用於 openssh 之 client 中,功用為發起連線。當中可以看到第 1282 行之 socket(),第 1285 行之 connect()以及第 1296 行之 close()此三個函式呼叫,使用 傳統使用資料探勘的程式分析方法,只能注意到此種 Pattern-僅包含函式呼叫,但是[2]

之研究注意到,變數也可成為 program rule 之中的重要成分,在上例中即為 sock 此變數 的使用,但[2]的方法是將函式及變數視為相同層級之分析實體(program entity),但並沒 有注意到其中的依賴(dependency)關係。

在此例中可以看到:

在 1282 行中函式 socket()將其回傳值置於 sock 此變數中,而 在 1285 行中函式 connect()以參數的方式讀進變數 sock。

在 1296 行中函式 close()以參數的方式讀進變數 sock。

以下即為所描述之圖示,這也是本篇論本所希望找出的 pattern。

圖 2 Dependency 示意圖

因此變數 sock 依於 socket(),而 connect()及 close()依於變數 sock,因此在此可以推斷 connect()及 close()的動作可能會依著函式 socket()每次回傳值的變異而有所不同。因此,

將變數 sock 以及函式 socket(),connect()以及 close()視為同一 pattern 為一合理的歸類法。

1.2.2. 使用專案版本庫

軟體專案的版本庫記載著專案原始碼中各種變動訊息,其中各個版本間的變動 差異可能是該專案的特殊情形,舉例來說,[6]分析各專案的版本資料庫以得到三種規則:

一.當程式中有部份的程式碼被修改時,自動預測或建議其它應共同修改部份;

二.在新版本加入後,依據以往的更新紀錄,偵測此次是否為不完整的更動;

三.傳統上對單一版本的程式分析有其弱點,特別是針對程式中不同 program entity 之歸類(coupling),加上版本資料庫的分析可以補其不足。

在本論文中,我們希望利用版本變動的部份特性以揀選出值得注意的 pattern,這些 pattern 中的單元可能是在以往在版本變動時曾發生過缺失,若能將此 pattern 予以挑出,

則在錯誤警示的功能上可以有更高的可信度。

1.3. 研究前提

從參考文獻與研究者的觀察中,這份論文設定下列前提,以此前提發展後續之研究:

1. 有連帶呼叫性質的函式有時會使用相同的變數,如圖 2 Dependency 示意圖圖 2 所揭示之的變數 sock,故若能以此變數為出發,則應可找出使用此變數同一 組的函示。

2. [7]的研究指出幾個現象,首先是50%以上的版本庫更動行數在十行以下,而

其中在只有一行更動的行為中,只有4%會造成以後程式的錯誤,且只有2.

5%是在完整地增加新功能,由此二原因我們推論,若大部份的一行更動不是 發展新功能,那麼它便可能是在修改舊程式,而修改舊程式的行為可合理地推 定為修正程式的錯誤。

3. 本研究將 pattern 限定在同一個函式呼叫的範圍內,即 intra-procedural。若採用 socket(…)

sock

connect(sock,…)

close(sock, …)

inter-procedural 之分析,則一來技術上會有相當大的困難,二來使用者反而會 因過多的資訊造成使用上的困難,使用 intra-procedural 分析則可以簡化其理解 上的複雜度。

1.4. 研究目的

綜合以上而言,這份論文希望達到幾個目的:

一是使用動態分析與 dataflow 分析,融合資料探勘的技術,針對特定專案找尋其常 用之 pattern,而 pattern 要能有以下的二個要求。

a. 找出的 pattern 可以明確的表達出當中元素執行上的先後次序;

b. 能夠反應出 pattern 內不同元素(program entity)之相依情況。

二是以版本資料庫為基礎,將高重要性的 pattern 挑出,供程式開發者建議。

1.5. 章節架構

本論文之第二章為近年來相關之研究,並以不同的研究途徑加以分類、比較,著重 在各論文使用之方法、優缺點及結果比較,後半段為本研究所使用之相關技術之說明。

第三章描述本論文所使用之方法,分為三個階段-取得分析資料、建立常用樣式以及常 見錯誤建議。第四章展示將此論文之方法應用於 OpenSSH[8]上。第五章總結本文之貢獻 與未來可能之研究方向。

相關文件