?

基于模板的軟件缺陷修復推薦方法

2022-05-10 08:45薄莉莉朱軒銳孫小兵
小型微型計算機系統 2022年5期
關鍵詞:源代碼調用開發人員

薄莉莉,朱軒銳,孫小兵

1(揚州大學 信息工程學院,江蘇 揚州 225127)

2(江蘇省知識管理與智能服務工程研究中心,江蘇 揚州 225127)

3(計算機軟件新技術國家重點實驗室(南京大學),南京 210023)

1 引 言

軟件缺陷種類繁多,產生原因多樣,造成結果復雜多變.往往缺陷的修復歷經不止一次的操作.通常,針對缺陷修復的問題,使用bug修復模板可以更快速地輔助開發人員解決缺陷問題.

早期的研究提出基于軟件缺陷模式產生有效的模板補丁來更準確、更快速地修復bug.例如:Kim等人[1]首先提出了基于模板的自動程序修復(APR),從超過6萬個人工補丁中學習并發現了一些常用的修復模板,這些模板能夠被補丁所接受,并修復bug.Osman等人[2]提出了一種從代碼更改歷史中提取bug修復模式的方法,統計修復模式,討論最常見的模式出現的原因.根據修復模式,可以更好地理解bug修復,提出更有效的bug解決方法.Negara等人[3]第一次提出從細粒度的代碼修改序列中識別未知的頻繁代碼修改模式,并分析修改模式,歸納了10種高級程序轉換模式.Zhao等人[4]開發了一種代碼更改自動分類工具CTforC,它依據代碼更改將其分成5種更改類型和9種更改子類型.雖然這些方法在修復bug方面有一定的幫助,剖析了較常用的修復模式,但是修復模板涉及人工手動分析,模板較單一,能提供的修復信息適合有針對性的代碼修復.

目前,深度學習技術廣泛應用于缺陷定位、缺陷預測和缺陷修復等方面[5-7].Tufano等人[8]提出使用深度學習的方法從真實程序的錯誤代碼和修復代碼中自動學習并生成突變體.他們利用RNN Encoder-Decoder構造一個神經機器轉換(NMT)模型,能夠確定在哪以及怎樣突變源代碼,創造了第一個用于自動化的從現有bug修復中學習變體的方法.在文獻[9]中,他們還對NMT模型進行了經驗性的研究,通過定性分析表明,該模型能夠學習和復制各種有意義的代碼更改,尤其是重構和bug修復操作.

為了提供細粒度的代碼更改,更好地幫助開發人員理解bug、解決bug問題.本文構建了一種自動識別細粒度更改操作的方法,通過分析常用的細粒度代碼更改操作并形成修復模板以運用到缺陷修復中.通過研究軟件bug模式,開發人員可以在測試過程中更快地對bug進行修復;也可以在開發過程中考慮采用什么樣的開發技術預防這些bug模式的再次出現,從而提高軟件開發和測試團隊的整體水平.

2 技術基礎

2.1 細粒度代碼更改

為了提高軟件的質量,必須盡早的理解bug.了解bug修復的更改操作,可以更好地理解bug的本質.在bug修復的類型中,有很多基于細粒度更改操作的擴展研究,可以使開發人員更好地了解代碼更改的性質.Negara等人[3]首先提出從細粒度的代碼更改序列中識別先前未知的頻繁更改操作模式,并分析修改模式,歸納了10種高級程序轉換模式,并利用23位開發人員收集的真實代碼進行評估,結果表明10種高級程序轉換模式是有效的,并適用于大部分數據.Osman等人[2]發現缺少null的檢查和初始化都是反復出現的錯誤,提出了一種自動提取錯誤修復模式的新方法.Campos等人[10]從提交修復操作的歷史庫中找到最常使用的更改操作模式,能夠有效地用于bug修復.

2.2 GumTree

GumTree[11]是一個可以生成源代碼編輯腳本的工具,編輯腳本表示兩個版本的源代碼之間的差異.傳統上,使用diff命令生成編輯腳本[12].而GumTree將兩個版本的源代碼作為輸入,并生成一個編輯腳本,該編輯腳本包含抽象語法樹(Abstract Syntax Tree,AST)的插入、刪除、更新和移動的節點,因此被用于許多更高級別的應用程序或進一步的研究中[13-16].GumTree的匹配算法包含兩個階段.第1個階段,GumTree匹配兩個AST的子樹.第2個階段,如果節點具有相同的類型并且節點的兩個子樹之間的Jaccard相似度超過閾值,則匹配子樹中的節點.通過經驗研究評估,GumTree可以有效地計算AST上的細粒度編輯腳本,并且比傳統的diff命令更易于理解.

由于GumTree比diff命令的解析粒度更細,考慮了語法信息,因此運用GumTree剖析bug修復中使用到的細粒度更改操作.通過對細粒度更改操作進行經驗性的研究,提取修復模板.

3 方 法

為了提高軟件缺陷修復效率,本文提出一種軟件缺陷修復推薦技術.方法流程如圖1所示.根據bug源代碼,首先定義適用于軟件缺陷的修復模板,然后利用基于樹的卷積神經網絡(Tree Based Convolutional Neural Networks,TBCNN)對bug源代碼進行分類,并根據每一類別推薦軟件缺陷修復模板.

圖1 方法流程圖

3.1 軟件bug修復模板構建

bug與其對應的源代碼之間有很強的關聯[17].源代碼是半結構化的文本,可以確定性地解析成抽象語法樹(AST),AST中的每個節點都是程序源代碼中的抽象組件.利用Java的AST可以從源碼中提取語義信息.

本文利用GumTree工具,獲取代碼的buggy版本及其對應的fixed版本的兩棵AST樹之間的差異,從而識別修復過程中已定義的17種細粒度的更改操作.該方法主要依賴GumTree解析代碼,節點識別來判斷具體的修復更改操作.首先從Github上爬取bug的源代碼文件,由于本文的細粒度的更改操作針對Java語言結構,所以僅挖掘源文件中后綴名為.Java的文件并且將其作為GumTree的輸入.然后通過GumTree解析buggy版本和fixed版本的差異語句,通過節點ID對應,找到具體的修改節點.差異語句中表示了從buggy版本到fixed版本所修復語句的操作,利用差異語句中的節點ID對應AST樹上的節點,很容易找到具體的修復節點.最后對該節點進行祖先遍歷判斷其細粒度更改操作的類型.通過對祖先節點的搜索,可以清楚地了解到修改的節點具體所屬的代碼位置,從而可以準確判斷出該節點的細粒度更改操作類型.其中刪除語句對應buggy版本的AST,插入語句對應fixed版本的AST,而移動語句則需要對應buggy版本和fixed版本的兩個AST.例如:某一GumTree解析后的差異語句是“Insert MethodInvocation(358) into InfixExpression:+(359) at 1”,即根據ID對應到fixed版本的AST樹,追蹤其父節點并判斷類型,意為“添加一個方法調用”.在判斷每一個差異語句之后,對于每一個bug修復,產生一個對應的修復節點序列.即,解析每一個GumTree輸出的差異語句,并轉換成我們之前研究[18]中預先定義的17種細粒度更改操作,形成更改操作序列.根據該序列,可以清晰地知道每一次修復基于代碼所做的更改操作.

由于在軟件開發和維護過程中通常進行軟件重用,軟件項目中的源代碼包含具有一定相似程度的代碼片段,會導致在源代碼上進行重復/相似的更改以及bug修復,這一點在先前的研究中[19-21]也得到了證實.本文首先提取方法級的更改操作序列,然后利用序列分析每一個序列中使用的細粒度更改操作.提取方法級的更改操作序列主要有4個方面的原因:1)方法很有可能執行一個單獨的任務;2)方法級提供了足夠有意義的上下文,例如變量、參數和方法調用.較小的代碼切片缺少必要的上下文.3)文件或類級別的粒度可能太大.4)任意長度的代碼切片(例如diff中的塊)可能會使模板更加復雜.此外,現有研究表明[10],缺陷主要發生在if相關語句、方法調用相關語句和賦值語句.因此,基于以上考慮,通過對代碼的理解并分析其他常見的軟件缺陷補丁中使用的修復模板,本文總結了8個修復模板.利用每個語句級別上重復使用的細粒度更改操作,構建修復模板,使得開發人員更有效地進行bug修復.

在Github上,每個項目都經過多次缺陷修復的提交.將本文的模板和每次提交中的代碼進行類型匹配,確認模板是在缺陷代碼中進行修復的,最終得出有效的細粒度修復模板.最后對該模板進行統計學分析,確保該模板是有效的,并且可以提高修復效率.下面將對每一種模板進行介紹.

模板1.IC-AS(if條件語句下賦值語句的修改)if條件的改動往往也會牽引該程序結構中其他語句的改動,if條件語句下的賦值語句也隨之修改.示例如表1第2行所示.

表1 軟件缺陷修復模板示例

模板2.WS-FC(while語句中方法調用的修改)while語句是常用的程序結構,方法調用亦是經常容易修改的細粒度更改操作,因此將其作為一個常用的修復模板.示例如表1第3行所示.

模板3.IC-FC(if條件下的方法調用的修改)if語句是java語言中最常用的程序結構,方法調用修改的頻率較高,因此將其作為一個常用的修復模板.示例如表1第4行所示.

模板4.FS-FC(for條件下的方法調用的修改)for語句是java語言中常用的程序結構之一,方法調用是最常見的修改,因此將其作為一個常用的修復模板.示例如表1第5行所示.

模板5.IF(if語句塊的添加)在處理異常的情況下,通常會在邊界值處理中添加一個if語句塊.示例如表1第6行所示.

模板6.RC(重復的操作)在不同的方法中添加相同的塊.在bug修復過程中,通常會在不同的地方,添加上相同的代碼塊,特別是處理異常的情況下.示例如表1第7行所示.

模板7.IF-P(添加if預測指針)這個類別的bug都是修復條件更改,涉及對某個對象添加空指針.這種類型的bug頻繁發生.示例如表1第8行所示.

模板8.AS-FC(賦值語句中方法調用的修改)賦值語句中的更改,往往會伴隨著方法調用語句的更改.示例如表1第9行所示.

3.2 軟件bug修復推薦方法

軟件缺陷修復推薦方法利用bug源代碼進行代碼分類,并為每一分類結果推薦修復模板.首先將得到的bug的buggy版本AST和fixed版本AST進行預處理,將兩個AST轉換成一個diff-AST.最終得到的diff-AST是在buggy版本的AST中改進的,使其具有更多的修復特征,從而提高基于樹的卷積神經網絡的分類特征獲取的準確性.

然后,運用基于樹的卷積神經網絡對代碼根據修復過程中所包含的細粒度更改操作進行分類.在修復方案推薦的方法構建中,需要對用于分類的bug數據先進行人工標記,依據修復缺陷過程中使用的細粒度更改操作的分類標準在人工干預的情況下將數據標記類別.在我們之前的經驗研究[18]中,對大量的bug進行了細粒度更改操作的分析,并將bug根據細粒度更改操作分為不同的類別.本文將8種修復模板作為修復方案推薦類別,通過分析修復代碼中的細粒度更改操作將bug數據標記為不同的修復方案類別.

數據標記完成之后,通過該卷積神經網絡學習不同修復方案類別的特征,并進行數據的分類.首先,將diff-AST樹作為輸入,并將AST節點表示為分布式實值向量,用來捕獲特征.其向量表示通過編碼標準來學習.接著,設計一組子樹特征檢測器,在整個AST上滑動以提取程序的結構信息,稱為基于樹的卷積核.然后,應用動態池化來收集樹的不同部分上的信息.最后,添加隱藏層和輸出層.對于監督分類任務,輸出層的激活函數為softmax,結果為每種分類的可能性.最終將可能性值最大的類別作為推薦類別以達到修復模板的推薦.

4 實驗評估

4.1 實驗對象

實驗對象來自Github上爬取的Mozilla項目的源代碼文件,包含bug的buggy版本和fixed版本.實驗數據依據Bugzilla——一個開源的bug追蹤系統(1)https://www.bugzilla.org,該系統關聯了Mozilla的bug數據,判斷bug是否完成了修復并且有最終的修復代碼,即在bug報告中是否包含“diff”.我們使用的是Bugzilla中包含“diff”的bug數據,截止到2018年10月,其數據量為1256.

4.2 實驗設置

問題1.本文提出的細粒度修復模板的使用頻率以及模板的覆蓋范圍如何?為了回答該問題,實驗中對細粒度的修復模板和真實項目中的commit提交的代碼進行匹配,以此判斷該修復模板使用的頻率.然后統計commit提交的代碼中所有的修復片段,計算8種模板使用情況的覆蓋范圍,以確定本文定義的修復模板的通用性.

問題2.本文推薦的修復模板的精確度如何?為了回答該問題,本實驗將通過基于樹的卷積神經網絡對bug文件進行推薦的修復模板與開發人員生成的補丁中的修復模式進行比較,來評估其準確性.為了衡量推薦方法的準確性,實驗選擇Mozilla項目中已完成修復的30個bug.我們利用公式(1)作為精確度的度量標準.其中P表示推薦的修復模板的準確率,nco表示能使用推薦的模板正確修復的bug的個數,Nco表示bug片段的總個數.這里的準確率為使用推薦模板正確修復bug的個數與實驗中所有bug片段個數的比例,該值越高,表示修復性能越好.

(1)

問題3.本文提出的推薦修復模板是否能有效為開發人員提供bug修復信息?面對真實項目中的大量代碼,運用本文推薦的修復模板,能否為開發人員提供有用的修復建議,這是本實驗的目的.在實驗中,讓參評人員根據推薦的修復模板去修復軟件bug,篩選有多少建議是可用的,并計算推薦修復模板的有效性.

4.3 實驗結果

問題1.本文提出的細粒度修復模板的使用頻率以及模板的覆蓋范圍如何?

通過將這些模板分別和每次commit提交中的代碼進行匹配分析,確保這些模板是在真實的項目中經常使用并且是有效的.細粒度模塊的使用頻率如圖2所示.在8種細粒度模板中,IC-AS模板的使用頻率最高,占總使用次數的21.83%.在bug修復中,if條件語句的修改,往往會伴隨著其他程序結構的修改,例如賦值語句的修改或方法調用語句的修改.IC-FC模板的使用頻率為16.91%,如果出現在賦值語句中修改了調用方法或者調用方法的實參,則將其認為是對賦值語句的修改,所以在本文的統計計算中,賦值語句的修改高于對方法調用語句的修改.其次,使用頻率較高的模板是AS-FC,占全部使用次數的19.73%.在賦值語句的修改中,簡單的賦值語句的修改在少數,即算術表達式和邏輯表達式,大部分還是對復雜的調用方法或者參數的修改.第3個使用頻率高的模板是IC-FC,所占比例為16.91%,即if語句中方法調用的修改.其他模板的使用頻率分別是,IF為11.64%,FS-FC為10.54%,WS-FC為10.2%,IF-P為5.64%,RC為3.51%.

圖2 細粒度模板的使用頻率

可以發現,在真實的項目中,大部分的模板修改的程序主要是對于if語句的修改,以及方法調用方法的修改.隨著軟件維護過程中,代碼量的不斷擴大,修復的程序類型也不止這8種,因此還另外計算了本文的模板在所有的代碼修復中所覆蓋的范圍.在隨機選取的項目中的1028個commit提交中,這8種基于細粒度的模板在修復代碼中覆蓋的范圍為67.11%.

綜上所述,本文所提出的8種細粒度的修復模板在真實的項目中使用是有效的,并且可以解決一半以上的bug問題,可以幫助開發人員快速地修復bug.

問題2.本文基于樹的卷積神經網絡推薦的修復方案的精確度如何?

實驗中選取的bug數據過濾掉了包含添加大量修復代碼、刪除大量源代碼以及大量修改代碼,修復包含明確的細粒度更改操作以至于可以更清晰地了解所推薦的修復方案是否正確.并且這些數據中的修復文件較少,且修復的代碼行中結構較為清晰.同時,30個數據不同于基于樹的卷積神經網絡的訓練集和測試集數據.首先30個bug報告將通過bug定位技術確定可疑的代碼行,然后將包含可疑代碼行的文件利用TBCNN將文件分類,最終選擇類別可能性值最高的類別作為可推薦的修復方案,并給出修復意見.該實驗針對最終推薦的30個修復方案,做統計分析.即通過推薦的修復方案和正確修復方案的比較,計算本文修復方案推薦方法的準確率.圖3表明了在30個bug中,推薦的修復模板在每個bug修復中使用的準確率.

圖3 推薦的修復模板使用的精確度

從圖3中可以看出,在分析的30個bug中,推薦的修復模板應用于具體的代碼修復中,準確率高于50%的達到了一半.這表明本文的細粒度修復模板是有效的,可以用于真實的代碼修復中.由于在真實的情況下,一些bug需要修復的代碼片段只有一個,或者太多(例如多于20個).這會造成修復模板的推薦受到限制,比如在bug #185165中,只修改了一處,即對if語句中的if條件進行了修改,而在本文的修復模板中不包含這類的修改,因此這會限制模板的使用.為了保證實驗驗證的有效性,選取的30個bug是隨機選取,只過濾掉了因為添加文件而造成的大范圍增加代碼的情況.而大范圍增加代碼進行修復的過程并不適合用模板修復,會造成模板的無效性.

在30個bug中,僅有16.67%的推薦的修復模板可以達到準確率100%的效果.造成這個結果的原因主要是,目前本文的修復模板雖然取自真實的項目中,但是在提取的過程中,由于一些技術因素導致模板并不全面,此模板的覆蓋范圍為67.11%.其次是在真實的項目中,程序結構多種多樣,并不絕對的限制在if條件中,而本文提取的修復模板大部分都是針對于if條件的修改,這會影響模板在驗證過程中的效果.

問題3.本文提出的推薦修復模板是否能有效為開發人員提供bug修復信息?

在這個研究問題中,旨在驗證修復模板是否符合開發人員想要的修復效果,能否為解決bug問題提供一些有效的信息.因此,為了驗證這個問題,實驗組織者邀請了5位參評者(對bug數據的研究超過兩年),根據推薦的修復模板,對推薦的信息有用性從3個等級進行評價:有用、一般有用、無用.其中,“有用”是指能夠幫助參評者實現bug問題的修復,“一般有用”是指僅能提供一部分的信息,“無用”是指推薦的信息對參評者起不到指導的作用.

圖4給出修復模板有效性評價結果.根據結果可知,通過推薦的修復模板提供的相關修復信息,對30個bug進行評估,其中對于參評者C,有46.67%的模板信息是有用的,43.33%的模板信息是一般有用的,僅有10%的模板信息是無用的.因此,可以認為90%的模板信息是有效的,能夠提供一些用于修復的指導意見.在其他參評者的反饋中,可以看出,大部分的修復模板方案是有效的,只有較少一部分提供的模板方案無效.造成這個結果的原因,可能是模板覆蓋不全面,小部分的bug僅修復一段代碼而這個修復操作不屬于本文的模板的覆蓋范圍.但是,從評價結果可知,本文提出的推薦修復模板方案能有效的提供一些bug修復相關的信息,可以幫助開發人員解決bug問題.

圖4 修復模板有效性評價結果

5 有效性威脅

首先,在本實驗中,利用基于樹的卷積神經網絡完成修復模板的推薦,在人工對訓練數據進行分類的過程中,可能存在一些人為的誤差,沒有經過專家認證,從而影響訓練數據集的準確性.

其次,在驗證過程中,選取的bug數據是隨機的,可能會導致模板的適用效果存在誤差.另一個有效性威脅是問題2中的參評者的評估存在偏差.為了緩解該問題,實驗中涉及的參評者都是具有開發經驗并且對bug數據有兩年以上的研究.

最后,本實驗中的實驗對象主要來源于Mozilla項目.雖然本文修復模板的提出是基于現有的大量大規模的經驗研究結果,但仍不能保證推薦的模板適用于所有的項目.在接下來的工作中,我們將收集更多開源項目中的缺陷數據,以保障實驗數據的充分性,從而進一步提升本文缺陷修復推薦方法的實用性.

6 總 結

本文主要針對bug修復耗時耗力的問題,利用bug報告,提出了一種基于樹的卷積神經網絡進行缺陷修復方案建議推薦的方法.從bug修復相關的源代碼中挖掘修復模板,并利用修復模板為開發人員推薦修復方案.為了驗證推薦的修復模板的有效性,本文使用Mozilla的bug數據對修復模板的精確度進行驗證,并邀請5名參評者對推薦的修復模板進行評估,結果表明本方法推薦的修復模板能夠有效地為開發人員解決bug問題時提供一些修復和指導意見.

猜你喜歡
源代碼調用開發人員
基于TXL的源代碼插樁技術研究
Semtech發布LoRa Basics 以加速物聯網應用
基于Android Broadcast的短信安全監聽系統的設計和實現
保護好自己的“源代碼”
解密別克安全“源代碼”
后悔了?教你隱藏開發人員選項
利用RFC技術實現SAP系統接口通信
三星SMI擴展Java論壇 開發人員可用母語
C++語言中函數參數傳遞方式剖析
91香蕉高清国产线观看免费-97夜夜澡人人爽人人喊a-99久久久无码国产精品9-国产亚洲日韩欧美综合