本發(fā)明涉及軟件調試,特別涉及一種可執(zhí)行程序編程優(yōu)化方法。
背景技術:
軟件調試在整個軟件開發(fā)中占據(jù)相當大的開銷。盡管軟件企業(yè)在軟件調試中已經(jīng)投入巨資,但軟件發(fā)行后仍然會被發(fā)現(xiàn)有嚴重的錯誤。在發(fā)行后再對軟件錯誤進行修補,仍會造成嚴重的經(jīng)濟損失。研究發(fā)現(xiàn),與軟件相關的安全事件,其中大都是由在設計或者編碼階段引入的軟件錯誤引起的。但確定一個靜態(tài)源碼檢測到的錯誤是否是一個真實的錯誤需要花費大量的精力。對于軟件錯誤的自動化檢測和修補,現(xiàn)有技術存在以下方案,即不關心待測程序的內部執(zhí)行情況,隨機的產(chǎn)生用例,觀察程序輸出是否與預期的相符合,但其缺陷是代碼覆蓋率低,因此其錯誤檢測能力有限。
技術實現(xiàn)要素:
為解決上述現(xiàn)有技術所存在的問題,本發(fā)明提出了一種可執(zhí)行程序編程優(yōu)化方法,包括:
步驟1:當監(jiān)控到待測程序的關鍵指令被執(zhí)行時,在路徑約束條件中輸入錯誤約束;
步驟2:根據(jù)外部函數(shù)的地址,利用插樁工具提供的api獲得外部函數(shù)名;
步驟3:對路徑進行遍歷搜索,求解新的路徑約束條件,產(chǎn)生觸發(fā)軟件錯誤的用例;
步驟4:監(jiān)控外部函數(shù)導致的符號傳遞,通過符號傳遞定位代碼錯誤。
優(yōu)選地,其中在路徑遍歷搜索過程中,首先接受初始用例作為其參數(shù),初始用例的邊界設置為0,表明執(zhí)行初始用例產(chǎn)生的路徑約束條件從深度0開始都被否定,以產(chǎn)生新的路徑約束條件;將初始用例加入到一個工作列表中;實際執(zhí)行待測程序,其輸入為初始用例,檢測初始用例能否觸發(fā)錯誤;當工作列表不為空時,則進入頂層循環(huán)的動態(tài)符號執(zhí)行;依據(jù)是用例的分值,從工作列表中選擇一個用例作為當前動態(tài)符號執(zhí)行的輸入,分值越高代表優(yōu)先級越高;對待測程序進行動態(tài)符號執(zhí)行,并生成新的用例集合;對集合中每一個用例進行實際執(zhí)行,檢測是否能夠觸發(fā)待測程序的錯誤,并對每個新用例進行評分;在檢測內存函數(shù)錯誤時,將所有的輸入標記為可疑點,表示所有的輸入都是不可信的,然后追蹤可疑點傳遞,當可疑點數(shù)據(jù)作為源操作數(shù)的時候,將指令的目的操作數(shù)也標記為可疑點,當可疑點數(shù)據(jù)傳遞到內存函數(shù)時,即可疑點數(shù)據(jù)作為內存函數(shù)的參數(shù)時,則找到內存函數(shù)錯誤;
在可疑點的數(shù)據(jù)結構上,采用一個連續(xù)的內存空間;給定一個虛擬地址addr,使用這個地址addr,找到可疑點數(shù)據(jù)結構的字節(jié)位置,再找到字節(jié)中的位偏移;如果這1位為1,表示對應的地址addr是可疑點數(shù)據(jù),如果是0則表示該地址不是可疑點數(shù)據(jù);
然后對可疑點傳遞進行追蹤,具體包括:注冊一個初始化回調函數(shù),對追蹤可疑點傳遞所需要的臨時數(shù)據(jù)結構進行初始化,該臨時數(shù)據(jù)結構存儲內存地址和寬度信息、寄存器、指令操作碼、指令類型,判斷是否是內存讀取操作,如果是則根據(jù)讀取的內存地址和內存操作數(shù)的大小,而將這些信息存儲到臨時數(shù)據(jù)結構中;判斷是否是內存修改操作,如果是則根據(jù)修改的內存地址和內存操作數(shù)的大小而將這些信息存儲到臨時數(shù)據(jù)結構中;獲得讀取的寄存器,將該寄存器信息存儲到臨時數(shù)據(jù)結構中;將該寄存器信息存儲到臨時數(shù)據(jù)結構中,將指令類型和指令操作碼信息存儲到臨時數(shù)據(jù)結構中;到臨時數(shù)據(jù)結構中查找所有被讀取的寄存器和內存地址,然后利用上述可疑點數(shù)據(jù)結構中查詢是否是可疑點,如果不是,則將記錄在臨時數(shù)據(jù)結構中的那些被修改的寄存器和內存地址的可疑點信息全部刪除;如果有任何一個寄存器或者內存地址是可疑點,則將記錄在臨時數(shù)據(jù)結構里的那些被修改的寄存器和內存地址全都標記為可疑點。
本發(fā)明相比現(xiàn)有技術,具有以下優(yōu)點:
本發(fā)明提出了一種可執(zhí)行程序編程優(yōu)化方法,在不降低代碼覆蓋率的前提下,提高了錯誤定位效率,優(yōu)化了代碼錯誤搜索過程。
附圖說明
圖1是根據(jù)本發(fā)明實施例的可執(zhí)行程序編程優(yōu)化方法的流程圖。
具體實施方式
下文與圖示本發(fā)明原理的附圖一起提供對本發(fā)明一個或者多個實施例的詳細描述。結合這樣的實施例描述本發(fā)明,但是本發(fā)明不限于任何實施例。本發(fā)明的范圍僅由權利要求書限定,并且本發(fā)明涵蓋諸多替代、修改和等同物。在下文描述中闡述諸多具體細節(jié)以便提供對本發(fā)明的透徹理解。出于示例的目的而提供這些細節(jié),并且無這些具體細節(jié)中的一些或者所有細節(jié)也可以根據(jù)權利要求書實現(xiàn)本發(fā)明。
本發(fā)明的一方面提供了一種可執(zhí)行程序編程優(yōu)化方法。圖1是根據(jù)本發(fā)明實施例的可執(zhí)行程序編程優(yōu)化方法流程圖。
本發(fā)明在代碼檢測系統(tǒng)中,通過產(chǎn)生用例而再現(xiàn)錯誤,向路徑約束條件中輸入錯誤約束,通過求解新的路徑約束條件,產(chǎn)生觸發(fā)軟件錯誤的用例;然后對外部函數(shù)進行建模,監(jiān)控外部函數(shù)導致的符號傳遞,而不增加約束,基于改進的優(yōu)化路徑遍歷搜索方法更快地執(zhí)行到錯誤路徑,從而能夠更快地檢測到代碼錯誤。
代碼檢測系統(tǒng)檢測當前運行路徑上的錯誤的錯誤約束,在當前運行路徑下當錯誤約束滿足時,則觸發(fā)錯誤,且得到的解就是能保證觸發(fā)錯誤的用例。代碼檢測系統(tǒng)對待測程序進行監(jiān)控,當關鍵指令被執(zhí)行時,主動在路徑約束條件中輸入錯誤約束,并對錯誤約束進行標記。
代碼檢測系統(tǒng)包括多個錯誤檢測單元,分別支持不同類型的錯誤檢測:數(shù)組越限、除零錯誤、空指針引用錯誤、函數(shù)參數(shù)錯誤。數(shù)組越限檢測單元用于檢測數(shù)組越限錯誤,追蹤符號傳遞,當有符號作為索引對數(shù)組進行訪問時,查詢當前棧幀范圍,獲得數(shù)組邊界,生成違反數(shù)組邊界要求的錯誤約束,并輸入到當前的路徑約束條件中;當新的路徑約束條件滿足時,則觸發(fā)數(shù)組越限錯誤。該數(shù)組越限檢測單元還用于符號索引追蹤,即追蹤符號從其他變量傳遞到數(shù)組的索引;數(shù)組操作識別,即通過逆向分析,將x86架構下的數(shù)組操作通過調整編譯選項而使得所有的數(shù)組操作都編譯為基址變址操作;和數(shù)組邊界檢測,即檢測數(shù)組的合法范圍,如果數(shù)組操作在合法范圍內則是合法的數(shù)組操作,否則數(shù)組越限,具體包括先進行反匯編,再反編譯,獲得具有數(shù)據(jù)結構信息的中間表達形式,再在中間表達形式的基礎上進行數(shù)組識別,識別數(shù)組后使用棧幀范圍來作為數(shù)組邊界的近似。除零錯誤檢測單元用于檢測除零錯誤,將div(無符號除)和idiv(帶符號除)兩種指令視為關鍵指令,當符號作為除數(shù)時,生成錯誤約束,并輸入到路徑約束條件中,最后通過求解新路徑約束條件,獲得可以觸發(fā)除零錯誤的用例。代碼檢測系統(tǒng)。空指針引用錯誤檢測單元用于檢測空指針引用錯誤。當一個符號作為地址被引用時,判斷地址是否與符號有關,并輸入到路徑約束條件中,通過求解新路徑約束條件,獲得可以觸發(fā)空指針引用錯誤的用例。函數(shù)參數(shù)錯誤檢測單元用于并對需要檢測的函數(shù)插樁,當關鍵函數(shù)被調用且函數(shù)參數(shù)與符號相關時則生成錯誤約束,并輸入到路徑約束條件中。為了對關鍵函數(shù)進行插樁,代碼檢測系統(tǒng)利用插樁工具pin對導出關鍵函數(shù)的映像文件進行插樁,當映像文件加載時,搜索映像文件中關鍵函數(shù)的位置,再對關鍵函數(shù)插樁。
當待測程序調用外部函數(shù)時,代碼檢測系統(tǒng)根據(jù)外部函數(shù)的地址,利用插樁工具提供的api獲得外部函數(shù)名。然后,根據(jù)外部函數(shù)的函數(shù)名判斷該函數(shù)是否有對應的函數(shù)模型,如果沒有,則實際執(zhí)行該函數(shù)。如果有對應的函數(shù)模型,判斷函數(shù)的參數(shù)是否與符號相關,如果函數(shù)的參數(shù)與符號相關,則執(zhí)行函數(shù)模型,追蹤符號傳遞,隨后進行實際執(zhí)行。
在路徑遍歷搜索過程中,首先接受初始用例作為其參數(shù)。初始用例的邊界設置為0,表明執(zhí)行初始用例產(chǎn)生的路徑約束條件從深度0開始都被否定,以產(chǎn)生新的路徑約束條件。將初始用例加入到一個工作列表中;實際執(zhí)行待測程序,其輸入為初始用例,檢測初始用例能否觸發(fā)錯誤。當工作列表不為空時,則進入頂層循環(huán)的動態(tài)符號執(zhí)行;依據(jù)是用例的分值,從工作列表中選擇一個用例作為當前動態(tài)符號執(zhí)行的輸入,分值越高代表優(yōu)先級越高;對待測程序進行動態(tài)符號執(zhí)行,并生成新的用例集合。對集合中每一個用例進行實際執(zhí)行,檢測是否能夠觸發(fā)待測程序的錯誤,并對每個新用例進行評分。
為了檢測內存函數(shù)錯誤,代碼檢測系統(tǒng)首先將所有的輸入標記為可疑點,表示所有的輸入都是不可信的,然后追蹤可疑點傳遞,當可疑點數(shù)據(jù)作為源操作數(shù)的時候,將指令的目的操作數(shù)也標記為可疑點。當可疑點數(shù)據(jù)傳遞到內存函數(shù)時,即可疑點數(shù)據(jù)作為內存函數(shù)的參數(shù)時,則找到了內存函數(shù)錯誤。
在可疑點的數(shù)據(jù)結構上,采用一個連續(xù)的內存空間。給定一個虛擬地址addr,使用這個地址addr,找到可疑點數(shù)據(jù)結構的字節(jié)位置,再找到字節(jié)中的位偏移。如果這1位為1,表示對應的地址addr是可疑點數(shù)據(jù),如果是0則表示該地址不是可疑點數(shù)據(jù)。然后對可疑點傳遞進行追蹤。具體包括:注冊一個初始化回調函數(shù),對追蹤可疑點傳遞所需要的臨時數(shù)據(jù)結構進行初始化。該臨時數(shù)據(jù)結構存儲內存地址和寬度信息、寄存器、指令操作碼、指令類型。判斷是否是內存讀取操作,如果是則根據(jù)讀取的內存地址和內存操作數(shù)的大小,而將這些信息存儲到臨時數(shù)據(jù)結構中;判斷是否是內存修改操作,如果是則根據(jù)修改的內存地址和內存操作數(shù)的大小而將這些信息存儲到臨時數(shù)據(jù)結構中。獲得讀取的寄存器。將該寄存器信息存儲到臨時數(shù)據(jù)結構中。將該寄存器信息存儲到臨時數(shù)據(jù)結構中。將指令類型和指令操作碼信息存儲到臨時數(shù)據(jù)結構中。到臨時數(shù)據(jù)結構中查找所有被讀取的寄存器和內存地址,然后利用上述可疑點數(shù)據(jù)結構中查詢是否是可疑點。如果不是,則將記錄在臨時數(shù)據(jù)結構中的那些被修改的寄存器和內存地址的可疑點信息全部刪除。如果有任何一個寄存器或者內存地址是可疑點,則將記錄在臨時數(shù)據(jù)結構里的那些被修改的寄存器和內存地址全都標記為可疑點。
對于空指針引用錯誤檢測,本發(fā)明還提供了一種可選的方式:
步驟1:讀取源文件,對其進行詞法分析和語法分析,利用輔助工具生成應用的語法樹,根據(jù)所述語法樹生成反映應用控制結構的控制流圖,并根據(jù)所述語法樹創(chuàng)建應用的符號表系統(tǒng)與類型系統(tǒng),基于語法樹識別出應用的全部可定位表達式,具體包括:基于語法樹識別出應用的所有定義的符號以及所有使用的可定位表達式;識別所有定義的函數(shù),并將識別的函數(shù)作為一個符號加入到相應作用域中;識別所有定義的結構體與聯(lián)合;并將識別出的結構體與聯(lián)合作為一個符號加入到相應作用域中;識別出結構體與聯(lián)合的成員,并加入到相應作用域中;識別所有定義的變量;其中,變量的類型為指針時,將變量作為一個指針類型符號添加到相應的作用域中,將指針的引用作為一個待識別的變量;變量的類型為數(shù)組時,將變量作為一個數(shù)組類型符號添加到相應的作用域中,將數(shù)組的每一個成員作為一個待識別的變量;變量的類型為結構體或聯(lián)合時,將變量作為一個結構體與聯(lián)合類型符號添加到相應的作用域中,將結構體與聯(lián)合的每一個成員作為一個待識別的變量;否則,將變量作為一個基本類型符號,添加到相應的作用域中?;谡Z法樹識別出應用的所有使用的可定位表達式,包括從語法樹上的后綴表達式節(jié)點識別所有使用的后綴表達式;從語法樹上的一元表達式節(jié)點識別所有使用的指針引用表達式。
對于識別出的可定位表達式,通過類型推導規(guī)則推導其類型。對于聲明的標志符變量,根據(jù)其聲明可知其類型。對于復雜數(shù)據(jù)類型的變量:(1)如果是數(shù)組,可知其元素的類型;(2)如果是指針,可知其指向的表達式的類型;(3)如果是結構體,可知其每個域成員的類型;對于不能通過聲明識別的表達式,通過類型推導規(guī)則推導出其類型。
步驟2:根據(jù)控制流圖產(chǎn)生時的節(jié)點號順序,取控制流圖中的下一個節(jié)點作為當前節(jié)點,如果所述當前節(jié)點為最后一個節(jié)點,則結束遍歷;所述生成函數(shù)摘要,對所述當前節(jié)點上第一次出現(xiàn)的變量,用基于區(qū)域的四元模型<variable,region,expression,domain>對所述變量進行建模,并根據(jù)所述變量的類型進行初始操作,包括:設置初始的區(qū)間值;若變量的類型是指針,設置其指向集合為空;其中,variable為被建模的所述變量,region為所述變量分配的抽象內存區(qū)域,expression為符號表達式,domain為取值區(qū)間;對所述當前節(jié)點的前驅節(jié)點上出現(xiàn)的除作用域的指針之外的每一個指針,求其在所述當前節(jié)點的所有前驅節(jié)點上的指向集合的并集,得到該指針在所述當前節(jié)點上的初始指向集合;其中,所述作用域為符號表系統(tǒng)中的作用域,用于存儲識別出的各類符號;對所述當前節(jié)點的前驅節(jié)點上出現(xiàn)的除作用域的變量之外的每一個變量,求其在所述當前節(jié)點的所有前驅節(jié)點上的取值區(qū)間或區(qū)間集的并集,得到該變量在所述當前節(jié)點上的初始取值區(qū)間或初始區(qū)間集,然后判斷在所述當前節(jié)點上是否存在某個變量的初始取值區(qū)間或初始區(qū)間集為空,若存在,則標記該節(jié)點為矛盾節(jié)點;若不存在,則根據(jù)所述當前節(jié)點所對應的語句類型,對該節(jié)點上每個已獲得初始指向集合的指針進行相應的指針分析,對該節(jié)點上的每個已獲得初始區(qū)間值或初始區(qū)間集的變量進行相應的區(qū)間運算。其中,當變量是基本類型時,用基于區(qū)域的四元模型對其進行建模,根據(jù)其具體類型設置初始區(qū)間;變量是數(shù)組元素時,建立數(shù)組的region與該變量region的父子層次關系;變量是結構體或聯(lián)合類型時,建立結構體或聯(lián)合的region與該變量的region的父子層次關系;變量是指針類型時,設置其指向集合為空,設置其初始狀態(tài)為unsure。
若所述當前節(jié)點所對應的語句類型為賦值語句,將指向集合的每一個抽象內存區(qū)域,其取值區(qū)間為變量當前的取值區(qū)間與右端表達式取值區(qū)間的并集;如果指向集合的抽象內存區(qū)域類型為指針類型,則每一個抽象內存區(qū)域的指向集合為當前指向集合與右端表達式指向集合的并集;若所述當前節(jié)點所對應的語句類型為條件語句,將該變量的每個成員作為一個被賦值變量,將右側表達式中的每一個對應的成員作為為該成員賦值的右側表達式,如果被賦值變量的類型為基本類型,則根據(jù)被賦值變量的類型及右端表達式計算該賦值語句中表達式的取值區(qū)間,并將所述被賦值變量的取值區(qū)間重置為該新計算出的表達式的取值區(qū)間;若所述當前節(jié)點所對應的語句類型為條件判斷語句,則對該節(jié)點所關聯(lián)的每一指針取初始的可能指向集后,分析該節(jié)點所關聯(lián)的每一指針在所述條件判斷語句中指向的可能集合和必然集合;對該節(jié)點所關聯(lián)的每一變量取初始的可能集后,計算該節(jié)點所關聯(lián)的每一變量在所述條件判斷語句中的取值的可能集和必然集,進而得到該節(jié)點所對應的控制流圖中真假分支上的所述變量取值情況;
所述生成函數(shù)摘要具體包括:生成函數(shù)摘要的前置約束條件;識別出需要被約束的、類型為指針的函數(shù)參數(shù)與全局變量;計算出被約束指針的弱約束條件。分析函數(shù)調用引起控制流發(fā)生改變的情況;計算函數(shù)的返回值。分析函數(shù)調用對指針類型形參與指針類型全局變量的指向關系與狀態(tài)的更新;分析函數(shù)調用對全局變量的數(shù)據(jù)流更新。
步驟3:根據(jù)所述函數(shù)摘要以及語法樹識別出全部的指針引用以及被引用的指針,并對每個被引用的指針創(chuàng)建空指針引用缺陷狀態(tài)機實例;在語法樹的一元表達式節(jié)點上識別出指針引用,以及被引用的指針;在語法樹的后綴表達式節(jié)點上識別出的指針引用,以及被引用的指針;在語法樹的一元表達式節(jié)點上識別出函數(shù)調用表達式;如果函數(shù)調用表達式對應的被調用函數(shù)有函數(shù)摘要時,則獲取函數(shù)摘要的前置約束條件,以及所述前置約束條件中全部被約束變量,將與所述被約束變量對應的實參或全局變量作為被引用的指針;如果函數(shù)調用表達式對應的被調用函數(shù)沒有函數(shù)摘要時,將傳遞給被調用函數(shù)的所有指針類型參數(shù)作為被引用的指針。
步驟4:基于控制流圖運行空指針引用缺陷狀態(tài)機實例,在控制流圖的每個節(jié)點上,根據(jù)區(qū)間運算、指針分析的結果對每個缺陷狀態(tài)機實例進行狀態(tài)遷移,確定安全指針引用集合、空指針引用集合、不確定的指針引用集合。
其中,賦值表達式的指針分析與區(qū)間運算過程具體包括:
判斷等號左側表達式的類型,若等號左側表達式為指針解引用,則根據(jù)等號右側不同表達式信息進行區(qū)間運算與指針分析;若等號左側表達式為指針變量,則根據(jù)等號右側不同表達式信息進行區(qū)間運算與指針分析;若等號左側表達式為復雜數(shù)據(jù)結構類型,根據(jù)等號右側不同表達式信息進行區(qū)間運算與指針分析;否則,將等號左側表達式的類型為基本數(shù)據(jù)類型,根據(jù)等號右側不同表達式信息進行區(qū)間運算與指針分析。
當左側表達式的類型為基本數(shù)據(jù)類型時,如果右側是指針解引用,則獲得右側被引用指針的指向集合,求得指向集合所指向的抽象內存區(qū)域的符號取值的并集,將左側變量的抽象內存區(qū)域的符號取值更新為所得并集;否則,將左側變量的抽象內存區(qū)域的符號取值更新為右側表達式的符號取值。當左側表達式的類型為被引用指針時,獲得左側被引用指針的指向集合,獲得指向集合對應的抽象內存區(qū)域集合;如果抽象內存區(qū)域均已被處理,結束對左側是指針解引用的賦值語句的處理;否則,取抽象內存區(qū)域集合中一個未被處理的抽象內存區(qū)域,然后判斷左側表達式類型是否為復雜數(shù)據(jù)類型,如果是,對抽象內存區(qū)域根據(jù)等號右側不同表達式信息進行區(qū)間運算,如果不是,對抽象內存區(qū)域根據(jù)等號右側不同表達式信息進行區(qū)間運算與指針分析。左側表達式的類型為指針變量時,將左側指針變量對應的抽象內存區(qū)域的指向集合置為空;判斷右側表達式是否為變量地址,若為變量地址,將右側地址變量對應的抽象內存區(qū)域添加到左側指針的抽象內存區(qū)域的指向集合,左側指針的抽象內存區(qū)域的取值為非空;若不為變量地址,分析右側指針表達式的指向集合與取值,將右側表達式的指向集合賦予給左側指針的抽象內存區(qū)域的指向集合,將右側表達式的取值賦值給左側指針的抽象內存區(qū)域的取值。
函數(shù)調用語句的指針分析與區(qū)間運算過程具體包括:獲得被調用函數(shù)的函數(shù)摘要;獲得函數(shù)摘要的后置約束條件,獲得后置約束條件中產(chǎn)生了副作用的引用類型的函數(shù)參數(shù)與全局變量;對產(chǎn)生了副作用的引用類型的函數(shù)參數(shù)與全局變量,基于后置約束條件更新其區(qū)間取值與指向信息。
在進行過程間分析創(chuàng)建函數(shù)摘要時,考慮到全部的被分析函數(shù)作用域內的變量包括頂級變量與成員變量。同時考慮到每個被約束變量的弱約束條件以。因此函數(shù)摘要的前置約束條件約束的變量是被解引用的指針類型的函數(shù)參數(shù)與全局變量、以及它們是指針類型的成員;函數(shù)摘要的后置約束條件是被該函數(shù)副作用影響的對指針類型的參數(shù)與全局變量及它們的成員;函數(shù)摘要的特征信息包括函數(shù)的返回值、控制流終止信息。
在面向對象程序中,對象是面向對象程序運行時的基本活動單位。因此本發(fā)明另一方面對每個類容器中的語句結合所屬對象的可疑率信息,區(qū)分不同類中具有相同覆蓋信息語句的可疑率,首先提取對象可疑率信息的提取方法;對象可疑率信息與語句頻率信息的結合方法。
在可疑率提取過程中,首先執(zhí)行多條失敗用例和多條成功用例,搜集每個對象的過程調用執(zhí)行軌跡;然后,把每個對象的過程調用執(zhí)行軌跡劃分為窗口大小為3的過程調用序列,根據(jù)用例執(zhí)行信息,生成過程調用序列頻率信息。使用四元組(aep,anp,aef,anf)表示過程調用序列頻率信息,其中aep,anp分別表示成功用例執(zhí)行和未執(zhí)行過程調用序列的數(shù)量,aef,anf分別表示失敗用例執(zhí)行和未執(zhí)行過程調用序列的數(shù)量。
然后,基于過程調用序列頻率信息以及搜集到的調試執(zhí)行結果向量,設計度量公式:
其中pass(p)=aep/(anp+aep)表示成功用例執(zhí)行過程調用序列p的百分比,fail(p)=aef/(anf+aef)表示失敗用例執(zhí)行過程調用序列p的百分比。
然后,利用上述計算的過程調用序列可疑率量化對象的可疑率信息:搜集每個對象的過程調用序列集合,把屬于同一個類的所有對象的過程調用序列集合合并為一個類的過程調用序列集合,該集合描述了該類在程序中的執(zhí)行行為;然后,把類的過程調用序列集合s(c)的平均可疑率作為該對象的可疑率w(c):
w(c)=∑p∈s(c)w(p)/t;
其中t=為s(c)中元素的個數(shù)。
把每條語句按照基于失敗用例執(zhí)行數(shù)目的分組策略分成若干組。通過分組策略,防止排名靠后的可疑語句結合對象可疑率信息后排名高于錯誤語句。
根據(jù)分組策略,假設將可疑語句分為1-n組,標記為g0,g1,g2,……,gn-1。gi中的下標i表示有i個失敗用例執(zhí)行了gi組內的可疑語句。每條可疑語句只包含在一個組內,可疑語句和組具有多對一的映射關系。給定語句s,算法的可疑率計算方式如下。
在上述公式中,tf代表失敗用例的總數(shù),c(s)表示包含語句s的類。w()表示相應對象的可疑率,m(s)表示由頻率錯誤定位過程計算得到的語句s可疑率;并且當s∈gi時,ti=1;否則ti=0。
在結合函數(shù)嵌套路徑信息的錯誤定位中,將函數(shù)嵌套路徑信息與程序頻率信息相結合,然后提供失效相關的函數(shù)嵌套路徑信息作為上下文信息,緩解程序頻率信息的局限性對錯誤定位效果的影響。
給定被測程序和相應的用例集,首先搜集函數(shù)嵌套邊剖面信息,構建加權的函數(shù)嵌套圖;然后,利用過程間函數(shù)嵌套路徑遍歷搜索算法搜索錯誤語句,對可疑語句在排序中的審查順序進行重新定義,并利用函數(shù)嵌套路徑信息將審查的語句關聯(lián)起來。
給定被測程序以及相應的用例集,靜態(tài)分析源代碼,獲得相應的函數(shù)嵌套圖。在函數(shù)嵌套圖中,每個節(jié)點表示—個函數(shù),每條邊對一個函數(shù)嵌套關系。插樁源代碼,執(zhí)行相應的用例集,搜集函數(shù)嵌套剖面信息,即每條函數(shù)嵌套邊的執(zhí)行信息。根據(jù)函數(shù)嵌套剖面信息,計算函數(shù)嵌套圖中每條邊的權重,建立加權的函數(shù)嵌套圖。基于加權的函數(shù)嵌套圖,按照預定義遍歷算法搜索錯誤,并記錄搜索錯誤過程中要檢測的可疑語句以及相應的函數(shù)嵌套路徑信息。將搜索過程中要審查的可疑語句進行定位錯誤。
在已有函數(shù)嵌套圖g(p)=<m,e>的基礎上,eij表示從mi到mj的嵌套關系。函數(shù)嵌套邊執(zhí)行剖面信息構建加權的函數(shù)嵌套圖。在加權函數(shù)嵌套圖中,每條函數(shù)嵌套邊具有一個權重,該權重表示相鄰兩個函數(shù)節(jié)點關系的緊密程度。如果用例t執(zhí)行了eij對應的函數(shù)嵌套,則記為eij被用例t所覆蓋。給定用例集t=tp∪tf其中表示tp成功調試用集,tf表示失敗用例集。ep(eij)={θ(eij,t1),θ(eij,t2),…θ(eij,tn)}表示調用邊eij的執(zhí)行剖面信息。當用例tk覆蓋了eij時,θ(eij,tk)=1;反之,θ(eij,tk)=0。成功用例集tp和失敗用例集tf關于eij執(zhí)行剖面信息分別記為epp(eij)和epf(eij),通過以下方法分別計算eij關于成功用例集和失敗用例集的執(zhí)行次數(shù)esp(eij)和esf(eij):
采用esp(eij)和esf(eij)的平均值作為每條調用邊eij的權值:
wt(eij)=(esp(eij)和esf(eij))/2
在基于基于加權的函數(shù)嵌套路徑的搜索時,通過遍歷加權函數(shù)嵌套圖搜索錯誤語句,同時搜集相關的函數(shù)嵌套路徑信息作為上下文幫助理解錯誤;重新定義中語句的排序,將獨立的不相關的語句進行關聯(lián)。
1.首先按照原排序選擇具有高可疑率的語句,或者屬于同一個函數(shù)的具有相同可疑率的語句,將包含這些語句的函數(shù)入棧,并作為加權函數(shù)嵌套圖中搜索的起點。
2.基于搜索起始節(jié)點,首先深度優(yōu)先搜索它的父節(jié)點,最多遍歷三層深度。在遍歷每層函數(shù)節(jié)點時,在該函數(shù)中具有較高可疑率的語句將按照順序進行審查,如果檢測的語句中包含錯誤語句,則遍歷算法停止;否則把該函數(shù)節(jié)點入棧,并選擇具有最大權重的鄰接邊作為要遍歷的下一條邊。當沒有邊可以遍歷或者深度己經(jīng)超過3時,回溯到棧中存放的上一個節(jié)點重復上述遍歷的過程。
3.當遍歷完該節(jié)點的父節(jié)點,并未搜索到錯誤語句,重復步驟2中的搜索過程深度優(yōu)先遍歷它的子節(jié)點。
4.記錄這一輪遍歷錯誤語句過程中需要審查的代碼,以及相應函數(shù)嵌套路徑信息。如果遍歷完相關函數(shù)節(jié)點未發(fā)現(xiàn)錯誤語句,則從步驟1開始繼續(xù)這個過程,直到檢查到錯誤語句為止。
對于步驟2和步驟3,在選擇下一條要遍歷的函數(shù)嵌套邊以及每個函數(shù)節(jié)點所要審查的可疑語句時,使用了如下啟發(fā)式過程:
在每次選擇下一個函數(shù)節(jié)點進行遍歷時,應選擇未遍歷的函數(shù)嵌套邊,以及至少一條失敗用例執(zhí)行了該函數(shù)嵌套邊,而且該函數(shù)嵌套邊具有最大的權值。在遍歷函數(shù)節(jié)點所包含的可疑語句時,只記錄如下可疑語句:在當前函數(shù)節(jié)點里未檢査,而且具有最高可疑率;在排序到這一輪遍歷的起始節(jié)點所記錄語句的排序距離不超過所有語句數(shù)量的10%。
綜上所述,本發(fā)明提出了一種可執(zhí)行程序編程優(yōu)化方法,在不降低代碼覆蓋率的前提下,提高了錯誤定位效率,優(yōu)化了代碼錯誤搜索過程。
顯然,本領域的技術人員應該理解,上述的本發(fā)明的各模塊或各步驟可以用通用的計算系統(tǒng)來實現(xiàn),它們可以集中在單個的計算系統(tǒng)上,或者分布在多個計算系統(tǒng)所組成的網(wǎng)絡上,可選地,它們可以用計算系統(tǒng)可執(zhí)行的程序代碼來實現(xiàn),從而,可以將它們存儲在存儲系統(tǒng)中由計算系統(tǒng)來執(zhí)行。這樣,本發(fā)明不限制于任何特定的硬件和軟件結合。
應當理解的是,本發(fā)明的上述具體實施方式僅僅用于示例性說明或解釋本發(fā)明的原理,而不構成對本發(fā)明的限制。因此,在不偏離本發(fā)明的精神和范圍的情況下所做的任何修改、等同替換、改進等,均應包含在本發(fā)明的保護范圍之內。此外,本發(fā)明所附權利要求旨在涵蓋落入所附權利要求范圍和邊界、或者這種范圍和邊界的等同形式內的全部變化和修改例。