記 關於 C OS II堆疊異常的原因剖析。

2021-10-01 02:32:54 字數 1423 閱讀 6734

在使用μc-os ii進行開發的時候,發現了乙個問題,對堆疊使用的時候發現在寫入flash的時候會出現宕機。使用了jtag進行除錯,發現當前的系統進入了硬體錯誤中斷(hardfaulthandle)。

根據手冊得知,當前硬體錯誤中斷觸發主要原因在於指標錯誤、記憶體溢位。所以我進行了詳細的尋找。因為系統的模組分布過多,因為系統的架構很好,基本上不會出現指標錯誤,所以說極有可能是因為記憶體溢位而導致系統錯誤。

我尋找了很長時間,下了很多的斷點,卻發現當前的系統出錯位置不固定,出錯時間不固定,但是大概都是在開機後一段時間。這個時間雖然不定,但是也較為固定。這就是我的乙個突破口。

順藤摸瓜,我找到了較為確定錯誤**,**是在寫入flash的函式內,函式邏輯主要是將當前需要寫入的資料存放在臨時快取中,再將臨時快取全部寫入flash。程式在執行到這裡時會不定時的出現錯誤,而錯誤時間還是不固定的。這個時候我已經基本確定問題在堆疊上面了,通過修改模組堆疊暫時規避了這個問題,但是問題只是被掩蓋了,並沒有被解決。

確定了問題肯定在這個模組堆疊的上面,但是我非常奇怪為什麼會出現這個奇怪的問題。我在**中插入了除錯**,將當前每個模組的最大堆疊占用的資料輸出,發現當進入寫入flash資料之前,堆疊暫時沒有任何變化,但是進入flash之後在任務切換出去的時候不會出現錯誤,但是執行幾行**之後就會報錯。在進行**查詢的時候,我發現在flash寫入之前定義了乙個資料快取,這個資料快取主要是簡化當前寫入資料的複雜性。而通過閱讀資料發現,這個資料快取會被編譯器儲存在任務棧中,這個快取遠遠大於當前的棧大小,發生了溢位。

找到問題之後解決就很方便,我才用指標變數直接讀取**入資料,使用sizeof函式進行待測資料的邊界測試。但是因為我使用了32位cpu,且使用了32位的指標。因為當前寫入的庫函式也是寫入32位資料,這裡就會有乙個問題,就是因為指標資料每次加一資料個數就會加4。所以務必注意需要將sizeof的結果除以4。而所有的計算機除法除了浮點型資料以外都會有錯誤。所以**應該這麼寫。

uint16 flashsize =0;

if((sizeof

(somethingbeingflash)/4

)==0)

else

這樣就可以避免日後出現加入不對其的資料導致資料少寫,而這個也是當初使用資料快取的原因之一。

這個問題主要在於編譯器對於堆疊資料處理的情況,查閱資料得知,棧資料主要存放各種臨時變數和資料,而堆資料主要是各種自定義資料。棧資料主要是編譯器維護,而堆資料由我們自己維護。所以在我寫入flash的時候,大量的資料快取區被定義,而在各個任務切換的時候,未被完全使用的臨時資料被壓入棧空間。所以錯誤是不確定的。而因為我的資料快取並沒有將所有資料使用完,所以編譯器貼心的沒有全部壓進棧。而這些資料因為μc-os ii的缺陷則很難被釋放。所以長期就會引起棧資料溢位。

這,還不是全部的根源。我對μc還不是精通,還有很多機制沒有搞清,相信到了我搞清這些機制的時候,就能完整的解釋這個問題。

待更。

程序中堆疊向下增長的原因

我們都知道x86系統程序中堆疊都向下增長的,那為什麼是向下增長呢?這個問題與虛擬位址空間的分配規則有關,每乙個可執行c程式,從低位址到高位址依次是 text,data,bss,堆,棧,環境引數變數 其中堆和棧之間有很大的位址空間空閒著,在需要分配空間的時候,堆向 棧往下漲。這樣設計可以使得堆和棧能夠...

程序中堆疊向下增長的原因

我們都知道x86系統程序中堆疊都向下增長的,那為什麼是向下增長呢?這個問題與虛擬位址空間的分配規則有關,每乙個可執行c程式,從低位址到高位址依次是 text,data,bss,堆,棧,環境引數變數 其中堆和棧之間有很大的位址空間空閒著,在需要分配空間的時候,堆向 棧往下漲。這樣設計可以使得堆和棧能夠...

消失的異常堆疊 jvm的fast throw

hotspot vm有個許多人覺得 匪夷所思 的優化,叫做fast throw 有些特定的隱式異常型別 nullpointerexception arithmeticexception 0 之類 如果在 裡某個特定位置被拋出過多次的話,hotspot server compiler c2 會透明的決...