新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 嵌入式軟件設(shè)計(jì)中查找缺陷的幾個(gè)技巧

嵌入式軟件設(shè)計(jì)中查找缺陷的幾個(gè)技巧

作者: 時(shí)間:2008-04-06 來源:網(wǎng)絡(luò) 收藏

本文引用地址:http://m.butianyuan.cn/article/258085.htm

確保永不發(fā)生堆棧溢出的唯一途徑就是分析代碼,確定程序在各種可能情況下的最大堆棧用量,然后檢查是否分配了足夠的堆棧。測試不大可能觸發(fā)特定的瞬時(shí)輸入組合進(jìn)而導(dǎo)致系統(tǒng)出現(xiàn)最壞情況。

  堆棧深度分析的概念比較簡單:

  1. 為每個(gè)獨(dú)立的線程建立一棵調(diào)用樹。

  2. 確定調(diào)用樹中每個(gè)函數(shù)的堆棧用量。

  3. 檢查每棵調(diào)用樹,確定從樹根到外部“樹葉”的哪條調(diào)用路徑需要使用的堆棧最多。

  4. 將每個(gè)獨(dú)立線程調(diào)用樹的最大堆棧用量相加。

  5. 確定每個(gè)中斷優(yōu)先級內(nèi)各中斷服務(wù)程序(ISR)的最大堆棧用量并計(jì)算其總和。但是,如果ISR本身沒有堆棧而使用被中斷線程的堆棧,則應(yīng)將ISR使用的最大堆棧數(shù)加到各線程堆棧之上。

  6. 對于每個(gè)優(yōu)先級,加上中斷發(fā)生時(shí)用來保存處理器狀態(tài)的堆棧數(shù)。

  7.如果使用RTOS,則加上RTOS自身內(nèi)部用途需要的最大堆棧數(shù)(與應(yīng)用代碼引發(fā)的系統(tǒng)調(diào)用不同,后者已包含在步驟2中)。

  除此之外,還有兩個(gè)重要事項(xiàng)需要考慮。首先,僅僅從高級語言源代碼建立的調(diào)用樹很可能并不完善。大部分編譯器采用運(yùn)行時(shí)庫(run-time library)來優(yōu)化常用計(jì)算任務(wù),如大值整數(shù)的乘除、浮點(diǎn)運(yùn)算等,這些調(diào)用只在編譯器產(chǎn)生的匯編語言中才可見。運(yùn)行時(shí)庫函數(shù)本身可能使用大量的堆棧空間,在分析時(shí)必須將它們包括進(jìn)去。如果使用的是C++語言,則以下所有類型的函數(shù)(方法)也都必須包含到調(diào)用樹內(nèi):結(jié)構(gòu)器、析構(gòu)器、重載運(yùn)算符、復(fù)制結(jié)構(gòu)器和轉(zhuǎn)換函數(shù)。所有的函數(shù)指針也都必須進(jìn)行解析,并且將它們調(diào)用的函數(shù)包含進(jìn)分析之中。

  第二,編譯器使用一個(gè)C庫來實(shí)現(xiàn)memcpy()、cos()和atof ()等標(biāo)準(zhǔn)函數(shù),而這些例程的源代碼可能無法得到。如果能夠得到它們的源代碼,就有可能確定程序用到的每個(gè)庫調(diào)用在最壞情況下的堆棧使用數(shù)量。如果這些庫只包含在目標(biāo)文件中,則編譯器廠商必須提供每個(gè)庫例程使用的堆棧數(shù)。如果沒有這些信息,就無法通過分析來確定最壞情況下程序使用的最大堆棧數(shù)。幸運(yùn)的是,許多面向嵌入式系統(tǒng)的編譯器廠商都提供這些信息。

  通常,每次一個(gè)函數(shù)被調(diào)用時(shí),編譯器將使用堆棧來保存返回地址并傳遞函數(shù)參數(shù)。函數(shù)的自動(局部)變量通常也在堆棧當(dāng)中。不過,由于編譯器會盡可能通過將參數(shù)或局部變量放入寄存器來優(yōu)化代碼,因此檢查匯編語言以精確地確定堆棧用量非常重要。編譯器也有可能在代碼中的其它地方選擇使用堆棧,如用堆棧來保存中間計(jì)算結(jié)果。

  有些與編譯器一起打包銷售的開發(fā)環(huán)境包含生成調(diào)用樹的工具,還有許多第三方的調(diào)用樹生成工具。但是,除非它們能夠?qū)R編語言進(jìn)行分析,否則這些工具可能會遺漏運(yùn)行時(shí)庫和C庫的調(diào)用。不過無論在哪種情況下,開發(fā)分析匯編語言文件并提取函數(shù)名稱以及各函數(shù)內(nèi)部調(diào)用的腳本都比較簡單。分析的結(jié)果可寫入一個(gè)文件,而這個(gè)文件能夠方便地輸入到表格之中。

  確定了各個(gè)函數(shù)的堆棧用量之后,必須計(jì)算每個(gè)線程所需的最大堆棧數(shù)。由于一般程序通常涉及數(shù)百個(gè)函數(shù),調(diào)用跨越多層深度,處理這些信息的一種簡便方法就是采用分析表格。如表1所示,表格的各行包含了函數(shù)名稱、該函數(shù)使用的最大堆棧數(shù)(包括調(diào)用其它函數(shù)所需的堆棧數(shù)),以及它調(diào)用的所有函數(shù)的清單。通過編程控制,這個(gè)表格從每個(gè)函數(shù)的根開始迭代循環(huán),計(jì)算該函數(shù)及其調(diào)用的所有函數(shù)需要的堆棧。這些信息存放在堆棧路徑列中,這樣,采用每個(gè)線程根函數(shù)(如main)的堆棧路徑數(shù)據(jù)就可以方便地計(jì)算出需要的最大堆棧數(shù)了。這個(gè)過程包含了先前介紹的堆棧分析過程中的前四個(gè)步驟。



評論


相關(guān)推薦

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

關(guān)閉