引子
前一篇文章介紹了堆棧和內(nèi)存的一些背景知識。本次介紹如何使用 Polyspace Code Prover來統(tǒng)計堆棧,如何使用這些數(shù)據(jù)為軟件優(yōu)化服務(wù)。
Polyspace Code Prover 堆棧統(tǒng)計
前面三類堆棧統(tǒng)計工具,在統(tǒng)計堆棧使用的時候,其需要編譯并運(yùn)行代碼,這意味著其需要定義測試激勵,這種情況的堆棧統(tǒng)計是特定測試激勵的,其他時候的堆棧大小則需要定義合適的測試激勵。而要統(tǒng)計軟件的最大堆棧需求,則需要設(shè)計合適的測試用例。這無疑對測試用例有比較高的要求。
形式化工具 Polyspace Code Prover 使用抽象解釋法,能夠深入探測到每一層函數(shù)的調(diào)用,統(tǒng)計每個函數(shù)本身的局部變量消耗和因?yàn)楹瘮?shù)調(diào)用需要的棧消耗。另外,由于形式化的方法的使用,Polyspace Code Prover 能夠分析代碼中的分支是否因?yàn)樯舷挛牡脑虿豢蛇_(dá)。這也會影響到實(shí)際程序中堆棧的大小。
Polyspace Code Prover能夠統(tǒng)計以下信息:
最大棧使用量
最小棧使用量
程序最大棧使用量
程序最小棧使用量
最大局部變量使用量
最小局部變量使用量
其中局部變量使用量統(tǒng)計包括本函數(shù)的局部變量,函數(shù)的參數(shù)和返回值的開銷,以及因?yàn)閮?nèi)存對齊導(dǎo)致的額外開銷等,而棧使用量則包括局部變量使用量以及函數(shù)需要調(diào)用其他函數(shù)導(dǎo)致的開銷。
程序的最大最小堆棧使用。當(dāng)程序中有main函數(shù)或者其他的入口函數(shù),Polyspace 可以統(tǒng)計主入口函數(shù)的總資源,其包括了調(diào)用其他函數(shù)需要的資源。

Polyspace 能夠提供函數(shù)的調(diào)用關(guān)系圖,據(jù)此可以看到一個函數(shù)的入口占用的資源是由于其調(diào)用了哪些函數(shù)帶來的。

如上圖我們知道入口函數(shù) ps_main 調(diào)用了 SysTick_Handler 函數(shù),也就是堆棧使用量 31 是 SysTick_Handler 調(diào)用引發(fā)的。


轉(zhuǎn)到 SysTick_Handler 也能看到的確如此。

更復(fù)雜的在 scheduler_executive 調(diào)用,從下面調(diào)用圖看到,其調(diào)用了多個函數(shù),而虛的三角型則代表是通過函數(shù)指針這類方式進(jìn)行非顯式調(diào)用的。

那么如何知道各個調(diào)用的函數(shù)的資源開銷呢,在上圖點(diǎn)擊轉(zhuǎn)到定義,然后可以立刻查看該函數(shù)的堆棧使用






從上面幾個圖可以很明顯的看到,update_shared_variables 占用了最多的資源。隨后我們可以繼續(xù)往下跟蹤。
何時執(zhí)行堆棧分析?
執(zhí)行堆棧分析是軟件開發(fā)生命周期中的一個連續(xù)過程。如果僅在軟件開發(fā)生命周期結(jié)束時由單獨(dú)的質(zhì)量評估團(tuán)隊(duì)估計堆棧使用量,則可能會使整個開發(fā)工作面臨風(fēng)險。此外,在開發(fā)周期的后期解決問題可能會出錯且耗時;在確定是更改硬件還是軟件設(shè)計時,這種做法可能還會造成混亂。
執(zhí)行堆棧分析的最佳時點(diǎn)是:
在添加新功能時
在軟件中每添加一項(xiàng)新功能,都會使堆棧使用量增加。開發(fā)人員必須密切關(guān)注新功能的堆棧使用情況。
執(zhí)行堆棧分析、進(jìn)行調(diào)試和修復(fù)復(fù)雜代碼:在每個主要功能實(shí)現(xiàn)后,開發(fā)人員可以在本地對特定軟件組件或軟件模塊應(yīng)用靜態(tài)分析器,以評估基礎(chǔ)軟件和已實(shí)現(xiàn)軟件之間堆棧使用量的增加情況。
在整個開發(fā)過程中監(jiān)控堆棧分析:QA 團(tuán)隊(duì)和產(chǎn)品負(fù)責(zé)人可以使用靜態(tài)分析器對持續(xù)集成 (CI) 管道進(jìn)行堆棧估計,以在控制板上顯示結(jié)果。此過程有助于在軟件開發(fā)生命周期中跟蹤堆棧分析。
執(zhí)行良好實(shí)踐以確保堆棧使用量最低:質(zhì)量門有助于避免違反 MISRA 和 AUTOSAR 編碼規(guī)范。這些規(guī)范要求強(qiáng)制有條件地使用動態(tài)內(nèi)存分配。
在軟件發(fā)布前
靜態(tài)分析器執(zhí)行的堆棧估計提供了有力的證據(jù),表明堆棧使用量處于控制之中。在每次軟件發(fā)布之前,都應(yīng)在標(biāo)準(zhǔn)工作負(fù)載、最小負(fù)載和最大負(fù)載下,對真實(shí)目標(biāo)運(yùn)行堆棧分析,以全面了解堆棧的使用情況。驗(yàn)證堆棧上溢和下溢事件的故障安全例程也至關(guān)重要。
根據(jù)堆棧統(tǒng)計進(jìn)行資源使用優(yōu)化
有了基礎(chǔ)的統(tǒng)計信息,結(jié)合 Polyspace 提供的函數(shù)調(diào)用圖,可以了解到在哪個位置,導(dǎo)致某個分支的堆棧使用量大增。
通過函數(shù)調(diào)用圖,我們知道整個程序的情況:

我們可以定位相對消耗較大的模塊,然后根據(jù)上述調(diào)用圖,定位到其調(diào)用的模塊,查看堆棧資源的消耗。
比如:

再到具體的函數(shù)中,查看其局部變量的消耗。
執(zhí)行良好實(shí)踐以確保堆棧使用量最低
對于產(chǎn)品級代碼,推薦遵循行業(yè)的編碼規(guī)范,如 MISRA C、MISRA C++、AUTOSAR C++ 等。這些編碼標(biāo)準(zhǔn)要求強(qiáng)制禁止動態(tài)內(nèi)存分配,并推薦特定用例來優(yōu)化靜態(tài)內(nèi)存分配。Polyspace Bug Finder 有助于識別任何違反最佳實(shí)踐的行為,開發(fā)人員可以在本地監(jiān)控這些行為,而產(chǎn)品負(fù)責(zé)人可通過 Polyspace Access 監(jiān)控這些行為。以下編碼規(guī)則詳細(xì)說明了靜態(tài)內(nèi)存分配的最佳實(shí)踐。靜態(tài)內(nèi)存分配可以使用 Polyspace Bug Finder 進(jìn)行分析。
以下是常見的編碼規(guī)范中關(guān)于內(nèi)存方面的部分。
| 編碼規(guī)范 | 規(guī)則 | 描述 |
|---|---|---|
| MISRA C:2004 | 20.4 | 不能使用動態(tài)堆內(nèi)存分配。 |
| MISRA C:2012 | 21.3 | 不能使用 的內(nèi)存分配和取消分配函數(shù)。 |
| MISRA C++:2008 | 18-4-1 | 不能使用動態(tài)堆內(nèi)存分配。 |
| AUTOSAR C++14 | A18-5-1 | 不能使用函數(shù) malloc、calloc、realloc 和 free。 |
| AUTOSAR C++14 | A18-5-2 | 不能使用非定位 new 或 delete 表達(dá)式。 |
| AUTOSAR C++14 | A18-5-3 | delete 表達(dá)式的形式應(yīng)與用于分配內(nèi)存的 new 表達(dá)式的形式保持一致。 |
| AUTOSAR C++14 | A18-5-4 | 如果為某個項(xiàng)目全局定義了運(yùn)算符“delete”的有大小或無大小版本,則應(yīng)同時定義有大小和無大小版本。 |
| AUTOSAR C++14 | A18-5-5 | 內(nèi)存管理函數(shù)應(yīng)確保以下各項(xiàng):(a) 行為是確定的,能夠預(yù)測出在最差情形下的執(zhí)行時間,(b) 避免內(nèi)存碎片化,(c) 避免運(yùn)行時出現(xiàn)內(nèi)存不足,(d) 避免不匹配的分配或取消分配,以及 (e) 不依賴對內(nèi)核的非確定性調(diào)用。 |
| AUTOSAR C++14 | A18-5-7 | 如果項(xiàng)目中使用動態(tài)內(nèi)存管理函數(shù)的非實(shí)時實(shí)現(xiàn),則只應(yīng)在非實(shí)時程序階段分配和取消分配內(nèi)存。 |
| AUTOSAR C++14 | A18-5-8 | 存活期不超過函數(shù)的對象應(yīng)具有自動存儲期。 |
| AUTOSAR C++14 | A18-5-9 | 動態(tài)內(nèi)存分配和取消分配函數(shù)的自定義實(shí)現(xiàn)應(yīng)滿足 C++ 標(biāo)準(zhǔn)中相應(yīng)“必要行為”條款中指定的語義要求。 |
| AUTOSAR C++14 | A18-5-10 | 定位 new 運(yùn)算符只能與對齊正確且指向足夠存儲容量的指針結(jié)合使用。 |
| AUTOSAR C++14 | A18-5-11 | 運(yùn)算符“new”和運(yùn)算符“delete”應(yīng)一起定義。 |
Polyspace 提供常見內(nèi)存問題的檢查
前一篇文章列舉的一些缺陷,Polyspace Bug Finder 和 Polyspace Code Prover 提供了許多針對靜態(tài)和動態(tài)內(nèi)存分配的運(yùn)行時檢查。解決所有高、中和低優(yōu)先級缺陷有助于降低內(nèi)存分配帶來的風(fēng)險。
Polyspace Bug Finder 關(guān)于內(nèi)存方面的檢查項(xiàng)

此外,Polyspace Code Prover提供內(nèi)存方面的形式化證明,包括
指針類型轉(zhuǎn)換錯誤
數(shù)組越界
結(jié)構(gòu)體指針越界
空指針或零地址解引用
對空指針偏移操作
位字段類型錯誤
malloc 返回值未檢查是否為 NULL
聯(lián)合體指針內(nèi)存分配不足
結(jié)構(gòu)體部分內(nèi)存分配
結(jié)構(gòu)體字段指針錯誤
函數(shù)返回局部變量指針
使用了已釋放的內(nèi)存無論使用何種方法來計算堆棧使用量,稍微增大堆棧大小都不失為一個好辦法。這種方法有助于避免測試期間可能未檢測到的堆棧溢出導(dǎo)致的系統(tǒng)漏洞。
堆棧溢出漏洞是許多嵌入式應(yīng)用程序在實(shí)際運(yùn)行中表現(xiàn)出不可定義行為的一個重要原因。在正確的時間使用正確的工具并遵循最佳實(shí)踐,可以增強(qiáng)對軟件防止堆棧溢出的信心。
-
程序
+關(guān)注
關(guān)注
117文章
3846瀏覽量
85232 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4417瀏覽量
67501 -
堆棧
+關(guān)注
關(guān)注
0文章
183瀏覽量
20524
原文標(biāo)題:堆棧知多少(二)如何進(jìn)行堆棧統(tǒng)計和優(yōu)化?
文章出處:【微信號:MATLAB,微信公眾號:MATLAB】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
Embedded Studio堆棧溢出預(yù)防功能
什么是堆棧溢出?如何分配堆棧空間大小?
XY圖數(shù)據(jù)統(tǒng)計-以長度為X軸來進(jìn)行統(tǒng)計
如何去實(shí)現(xiàn)一種CPU利用率及堆棧檢測統(tǒng)計
基于QR Code條碼的飛機(jī)加油統(tǒng)計系統(tǒng)
HT MCU 軟件堆棧的應(yīng)用
合泰單片機(jī)HT48軟件堆棧的應(yīng)用
堆棧指針sp的內(nèi)容是什么
關(guān)于Polyspace應(yīng)用到基于模型的設(shè)計可能性分析和介紹
關(guān)于Polyspace靜態(tài)分析的具體作用分析和介紹
什么是單片機(jī)堆棧?單片機(jī)堆棧有什么作用和原理說明
單片機(jī)堆棧是什么?它的原理和作用又是什么?
使用Python DIY Arduino來顯示PC統(tǒng)計數(shù)據(jù)
Embedded Studio堆棧溢出預(yù)防簡析
堆棧和內(nèi)存的基本知識
如何使用Polyspace Code Prover來統(tǒng)計堆棧
評論