新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 查找嵌入式C語言程序/軟件中的缺陷的多種技術(shù)

        查找嵌入式C語言程序/軟件中的缺陷的多種技術(shù)

        作者: 時(shí)間:2010-11-23 來源:網(wǎng)絡(luò) 收藏


        然后我們重新運(yùn)行程序,將不會(huì)再報(bào)告任何內(nèi)存錯(cuò)誤。當(dāng)我們把程序上載到目標(biāo)板上時(shí),它似乎如我們預(yù)期那么在工作了。盡管如此,我們?nèi)匀挥幸恍?dān)心。

        我們僅到我們所執(zhí)行的代碼路徑中的一個(gè)內(nèi)存寫溢出實(shí)例,我們憑什么能夠斷定我們尚未執(zhí)行到的代碼就不會(huì)有內(nèi)存寫溢出錯(cuò)誤了呢?如果我們檢查覆蓋率分析,我們就會(huì)發(fā)現(xiàn)reportSensorFailure()這個(gè)函數(shù)從未被執(zhí)行到。我們有必要對這個(gè)函數(shù)進(jìn)行測試,但是具體如何進(jìn)行呢?建立一個(gè)調(diào)用該函數(shù)的單元測試用例就是一個(gè)不錯(cuò)的辦法。

        在單元測試中使用運(yùn)行時(shí)內(nèi)存監(jiān)測:我們使用C++test的測試用例向?qū)韯?chuàng)建一個(gè)測試用例的框架,并向其中添加一些測試代碼。然后運(yùn)行該測試用例——以檢查上面提到的未經(jīng)測試的函數(shù),同時(shí)打開運(yùn)行時(shí)內(nèi)存監(jiān)測功能。使用C++teST,全過程大約只需要數(shù)秒鐘。

        結(jié)果標(biāo)明該函數(shù)已經(jīng)被覆蓋到了,但同時(shí)也到了新的錯(cuò)誤:

        本文引用地址:http://www.104case.com/article/151316.htm

        我們的測試用例到了更多的內(nèi)存相關(guān)錯(cuò)誤。很顯然,當(dāng)失敗處理函數(shù)被調(diào)用時(shí),我們的內(nèi)存初始化存在問題(空指針)。通過更進(jìn)一步的分析,我們發(fā)現(xiàn)在reportSensorValue()函數(shù)中存在函數(shù)調(diào)用順序錯(cuò)誤。

        finalize()函數(shù)先于printMessage()函數(shù)被調(diào)用,但是finalize()函數(shù)中釋放了printMessage()函數(shù)需要使用的內(nèi)存。

        void finalize()
        {
        if (messages) {
        free(messages[0]);
        free(messages[1]);
        free(messages[2]);
        }
        free(messages);
        }

        將函數(shù)調(diào)用順序進(jìn)行修改后,我們重新運(yùn)行程序。

        這樣我們就解決了上面報(bào)告中的第一個(gè)錯(cuò)誤。現(xiàn)在我們再來分析報(bào)告中的第二個(gè)錯(cuò)誤:即打印信息中的AccessViolatiONException。產(chǎn)生這個(gè)錯(cuò)誤的原因是相應(yīng)的消息列表未經(jīng)初始化。為了解決該問題,我們在打印該信息前調(diào)用一次initialize()函數(shù)來對其進(jìn)行初始化。經(jīng)修改后的函數(shù)如下所示:

        void reportSensorFailure()
        {
        initialize();
        printMessage(ERROR, 0);
        finalize();
        }

        當(dāng)我們再次運(yùn)行該測試用例時(shí),僅有一個(gè)任務(wù)被報(bào)告出來:未經(jīng)驗(yàn)證的單元測試用例(an unvalidated unit test case),這其實(shí)并不算一條錯(cuò)誤。我們只需對輸出進(jìn)行一下驗(yàn)證,以將該測試用例轉(zhuǎn)換為回歸測試。通過創(chuàng)建合適的斷言,C++test會(huì)自動(dòng)為我們完成這些步驟。

        接下來我們再次運(yùn)行整個(gè)程序。覆蓋率分析告訴我們幾乎整個(gè)程序都已經(jīng)被覆蓋到了,并且沒有發(fā)現(xiàn)任何內(nèi)存錯(cuò)誤。

        這樣就結(jié)束了嗎?其實(shí)不然。雖然我們運(yùn)行了整個(gè)程序并為未覆蓋到的函數(shù)創(chuàng)建了單元測試用例,但還是有一些路徑是沒有被覆蓋到的。我們?nèi)匀豢梢岳^續(xù)創(chuàng)建單元測試用例,但是若指望通過這樣的方法來覆蓋程序中的所有路徑將耗費(fèi)相當(dāng)長的時(shí)間。或者我們使用另外的方法,使用數(shù)據(jù)流分析來對這些路徑進(jìn)行模擬。

        數(shù)據(jù)流分析

        我們使用C++test的BugDetective來進(jìn)行數(shù)據(jù)流分析,BugDetective能模擬系統(tǒng)中的不同路徑并檢查這些路徑中是否存在潛在的問題。進(jìn)行數(shù)據(jù)流分析后,我們得到如下結(jié)果:

        仔細(xì)分析報(bào)告的結(jié)果,我們發(fā)現(xiàn)程序中存在一條未被覆蓋到的潛在路徑可能會(huì)造成在finalize()函數(shù)中出現(xiàn)兩次free的操作。在程序中,reportSensorValue()函數(shù)調(diào)用了finalize()函數(shù),然后finalize()函數(shù)調(diào)用了free()。同時(shí),finalize()函數(shù)還會(huì)被mainLoop()函數(shù)調(diào)用。我們可以修改finalize()函數(shù)以使其更加智能化,從而修復(fù)這個(gè)問題,修改后的代碼如下:

        void finalize()
        {
        if (messages) {
        free(messages[0]);
        free(messages[1]);
        free(messages[2]);
        free(messages);
        messages = 0;
        }
        }

        現(xiàn)在我們再次運(yùn)行數(shù)據(jù)流分析,得到的結(jié)果將只有兩個(gè)問題:

        這里我們可能使用了-1作為索引來訪問了數(shù)組。這是由于整型變量index被設(shè)置的初始值為-1,并且存在一條可能通過if語句的路徑在未將該整型變量正確的進(jìn)行初始化之前便調(diào)用了printMessage()函數(shù)。運(yùn)行時(shí)分析未檢查到這樣的一條路徑,并且該路徑很有可能在真實(shí)世界中永遠(yuǎn)不可能被執(zhí)行到。這就是靜態(tài)數(shù)據(jù)流分析相對于運(yùn)真實(shí)運(yùn)行時(shí)內(nèi)存監(jiān)測最主要的不足:數(shù)據(jù)流分析能檢查出潛在的路徑,這些路徑可能包含在程序?qū)嶋H執(zhí)行過程中不會(huì)執(zhí)行到或不存在的路徑。盡管如此,為了做到有備無患,我們刪除了上述的不必要的條件(value>=0)以修改這個(gè)潛在的錯(cuò)誤。

        linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)


        評論


        相關(guān)推薦

        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 彩票| 镇康县| 阆中市| 西峡县| 包头市| 时尚| 台东市| 武鸣县| 锦屏县| 武宁县| 新建县| 嵊州市| 泌阳县| 常宁市| 泗阳县| 浏阳市| 扬州市| 泊头市| 科尔| 内江市| 无锡市| 惠安县| 黄骅市| 潢川县| 竹北市| 扶风县| 宣恩县| 阿图什市| 东莞市| 化德县| 富源县| 徐州市| 攀枝花市| 许昌县| 新兴县| 西乡县| 札达县| 科尔| 高阳县| 永泰县| 青田县|