導航:首頁 > 操作系統 > 單片機棧溢出

單片機棧溢出

發布時間:2023-04-22 01:24:40

單片機 C語言 遞歸

單片機內亂喚存有限,據我所知,內存中分3部分,一部分放程序指令者豎,一部分作為堆用,一部分作為棧,這里用遞歸了,每次調用函數會把當前狀態壓棧,沒有結束,那樣存儲空間不夠,棧溢出,單片機系統嘩嫌凱不會復位,但是程序會亂跑。個人理解而已。

❷ C語言局部變數過多會不會造成棧區堆滿

答案是會的:扮卜
系統分配給每個程序的棧空間是有限的,超過了就會堆滿。
最有代表性的就是遞歸函數,如果遞歸的深度達到一定量,程序棧就會滿,程序就會異常退出閉清,之前使用快速排序用到遞歸,當數據量比較大,數據基本有序時遞歸深度就比較大,程序就停止了,廳態穗調試錯誤顯示棧資源不足。

❸ 單片機引腳配置錯誤為什麼會導致程序出錯

在平常的項目開發過程中,會遇到各種各樣的問題。下面分享一篇文章,是常見問題的解決思路和辦法。
一、問題復現
穩定復現問題才能正確的對問題進行定位、解決以及驗證。一般來說,越容易復現的問題越容易解決。
1.1 模擬復現條件
有的問題存在於特定的條件下,只需要模擬出現問題的條件即可復現。對於依賴外部輸入的條件,如果條件比較復雜難以模擬可以考慮程序里預設直接進入對應狀態。
1.2 提高相關任務執行頻率
例如某個任務長時間運行才出現異常則可以提高該任務的執行頻率。
1.3 增大測試樣本量
程序長時間運行後出現異常,問題難以復現,可以搭建測試環境多套設備同時進行測試。
二、問題定位
縮小排查范圍,確認引入問題的任務、函數、語句。
2.1 列印LOG
根據問題的現象,在抱有疑問的代碼處增加LOG輸出,以此來追蹤程序執行流程以及關鍵變數的值,觀察是否與預期相符。
2.2 在線調試
在線調試可以起到和列印LOG類似的作用,另外此方法特別適合排查程序崩潰類的BUG,當程序陷入異常中斷(HardFault,看門狗中斷等)的時候可以直接STOP查看call stack以及內核寄存器的值,快速定位問題點。
2.3 版本回退
使用版本管理工具時可以通過不斷回退版本並測試驗證來定位首次引入該問題的版本,之後可以圍繞該版本增改的代碼進行排查。
2.4 二分注釋
以類似二分查找法的方式注釋掉部分代碼,以此判斷問題是否由注釋掉的這部分代碼引起。
具體方法為將與問題不相乾的部分代碼注釋掉一半,看問題是否解決,未解決則注釋另一半,如果解決則繼續將注釋范圍縮小一半,以此類推逐漸縮小問題的范圍。
2.5 保存內核寄存器快照
Cortex M內核陷入異常中斷時會將幾個內核寄存器的值壓入棧中,如下圖:

我們可以在陷入異常中斷時將棧上的內核寄存器值寫入RAM的一段復位後保留默認值的區域內,執行復位操作後再從RAM將該信息讀出並分析,通過PC、LR確認當時執行的函數,通過R0-R3分析當時處理的變數是否異常,通過SP分析是否可能出現棧溢出等。
三、問題分析處理
結合問題現象以及定位的問題代碼位置分析造成問題的原因。
3.1 程序繼續運行
3.1.1 數值異常3.1.1.1 軟體問題
1、數組越界
寫數組時下標超出數組長度,導致對應地址內容被修改。旦凱雹如下:

此類問題通常需要結合map文件進行分析,通過map文件觀模帆察被篡改變數地址附近的數組,查看對該數組的寫入操作是否存在如上圖所示不安全的代碼,將其修改為安全的代碼。
2、棧溢出
0x20001ff8
g_val
如上圖,此類問題也需要結合map文件進行分析。假設棧從高地址往低地址增長,如果發生棧溢出,則g_val的值會被棧上的值覆蓋。
出現棧溢出時要分析棧的最大使用情況,函數調用層數過多,中斷服務函數內進行函數調用,函數內部申明了較大的臨時變數等都有可能導致棧溢出。
解決此類問題有以下方法:
在設計階段應該合理分配內存資源,為棧設置合適的大小;
將函數內較大的臨時變數加」static」關鍵字轉化為靜態變數,或者使用malloc()動態分配,將其放到堆上;
改變函數調用方式,降低調用層數。
3、判斷語句條件寫錯
判斷語句的條件容易把相等運算符「==」寫成賦值運算符「=」導致被判斷的變數值被更改,該類錯誤編譯期不會報錯且總是返回真。
建議將要判斷的變數寫到運算符的右邊,這樣錯寫為賦值運算符時會在編譯期報錯。還可以使用一些靜態代碼檢查工具來發現此類問題。
4、同步問題
例如操作隊列時,出隊操作執行的過程中發生中斷(任務切換),並且在中斷(切換後的任務)中執行入隊操作則可能破壞隊列結構,對於這類情況應該操作時關中斷(使用互斥鎖同步)。
5、優化問題
如上圖程序,本意是等待irq中斷之後不再執行foo()函數,但被編譯器優化之後,實際運行過程中flg可能被裝入寄存器並且每次都判斷寄存器內的值而不重新從ram里讀取flg的值,導致即使irq中斷發生foo()也一直運行,此處需要在flg的申明前加「volatile」關鍵字,強制每次都從ram里獲取flg的值。
3.1.1.2 硬孫悔件問題
1、晶元BUG
晶元本身存在BUG,在某些特定情況下給單片機返回一個錯誤的值,需要程序對讀回的值進行判斷,過濾異常值。
2、通信時序錯誤
例如電源管理晶元Isl78600,假設現在兩片級聯,當同時讀取兩片的電壓采樣數據時,高端晶元會以固定周期通過菊花鏈將數據傳送到低端晶元,而低端晶元上只有一個緩存區.
如果單片機不在規定時間內將低端晶元上的數據讀走那麼新的數據到來時將會覆蓋當前數據,導致數據丟失。此類問題需要仔細分析晶元的數據手冊,嚴格滿足晶元通信的時序要求。
3.1.2 動作異常3.1.2.1 軟體問題
1、設計問題
設計中存在錯誤或者疏漏,需要重新評審設計文檔。
2、實現與設計不符
代碼的實現與設計文檔不相符需要增加單元測試覆蓋所有條件分支,進行代碼交叉review。
3、狀態變數異常
例如記錄狀態機當前狀態的變數被篡改,分析該類問題的方法同前文數值異常部分。
3.1.2.2 硬體問題
1、硬體失效
目標IC失效,接收控制指令後不動作,需要排查硬體。
2、通信異常
與目標IC通信錯誤,無法正確執行控制命令,需要使用示波器或邏輯分析儀去觀察通信時序,分析是否發出的信號不對或者受到外部干擾。
3.2 程序崩潰
3.2.1 停止運行3.2.1.1 軟體問題
1、HardFault
以下情況會造成HardFault:
在外設時鍾門未使能的情況下操作該外設的寄存器;
跳轉函數地址越界,通常發生在函數指針被篡改,排查方法同數值異常;
解引用指針時出現對齊問題:
以小端序為例,如果我們聲明了一個強制對齊的結構體如下:
地址
此時a.val1的地址為0x00000001,如果以uint16_t類型去解引用此地址則會因為對齊問題進入HardFault,如果一定要用指針方式操作該變數則應當使用memcpy()。
2、中斷服務函數中未清除中斷標志
中斷服務函數退出前不正確清除中斷標志,當程序執行從中斷服務函數內退出後又會立刻進入中斷服務函數,表現出程序的「假死」現象。
3、NMI中斷
調試時曾遇到SPI的MISO引腳復用NMI功能,當通過SPI連接的外設損壞時MISO被拉高,導致單片機復位後在把NMI引腳配置成SPI功能之前就直接進入NMI中斷,程序掛死在NMI中斷中。這種情況可以在NMI的中斷服務函數內禁用NMI功能來使其退出NMI中斷。
3.2.1.2 硬體問題
1、晶振未起振
2、供電電壓不足
3、復位引腳拉低
3.2 .2 復位3.2.2.1 軟體問題
1、看門狗復位
除了喂狗超時導致的復位以外,還要注意看門狗配置的特殊要求,以Freescale KEA單片機為例,該單片機看門狗在配置時需要執行解鎖序列(向其寄存器連續寫入兩個不同的值),該解鎖序列必須在16個匯流排時鍾內完成,超時則會引起看門狗復位。此類問題只能熟讀單片機數據手冊,注意類似的細節問題。
3.2.2.2 硬體問題
1、供電電壓不穩
2、電源帶載能力不足
四、回歸測試
問題解決後需要進行回歸測試,一方面確認問題是否不再復現,另一方面要確認修改不會引入其他問題。
五、經驗總結
總結本次問題產生的原因及解決問題的方法,思考類似問題今後如何防範,對相同平台產品是否值得借鑒,做到舉一反三,從失敗中吸取經驗。
(涉及領域:電子、電氣/電工(考證題庫)、通信、維修、自動化、程序等)
大傢伙都關注了這個公眾號"電子技術控"
點個「贊+在看+分享+收藏」4連
免責聲明
本文來自騰訊新聞客戶端創作者,不代表騰訊新聞的觀點和立場。
打開騰訊新聞,閱讀體驗更好
廣告
血糖7.0以上,飯後一個習慣,血糖高連夜改善!
打開
騰訊新聞
參與討論
血糖7.0以上,飯後一個習慣,血糖高連夜改善!
廣告
長興

❹ 堆和棧的區別是啥

堆和棧的區別:
一.堆棧空間分配區別:

1.棧(操作系統):由操作系統自動分配釋放 ,存放函數的參數值,局部變數的值等。其操作方式類似於數據結構中的棧;

2.堆(操作系統): 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收,分配方式倒是類似於鏈表。

二.堆棧緩存方式區別:

1.棧使用的是一級緩存, 他們通常都是被調用時處於存儲空間中,調用完畢立即釋放;

2.堆是存放在二級緩存中,生命周期由虛擬機的垃圾回收演算法來決定(並不是一旦成為孤兒對象就能被回收)。所以調用這些對象的速度要相對來得低一些。

三.堆棧數據結構區別:

堆(數據結構):堆可以被看成是一棵樹,如:堆排序;

棧(數據結構):一種先進後出的數據結構。

(4)單片機棧溢出擴展閱讀:

堆支持以下的基本:

1.build:建立一個空堆;

2.insert:向堆中插入一個新元素;

3.update:將新元素提升使其符合堆的性質;

4.get:獲取當前堆頂元素的值;

5.delete:刪除堆頂元素;

6.heapify:使刪除堆頂元素的堆再次成為堆。

某些堆實現還支持其他的一些操作,如斐波那契堆支持檢查一個堆中是否存在某個元素。

棧的基本演算法

1.進棧(PUSH)演算法

①若TOP≥n時,則給出溢出信息,作出錯處理(進棧前首先檢查棧是否已滿,滿則溢出;不滿則作②);

②置TOP=TOP+1(棧指針加1,指向進棧地址);

③S(TOP)=X,結束(X為新進棧的元素);

2.退棧(POP)演算法

①若TOP≤0,則給出下溢信息,作出錯處理(退棧前先檢查是否已為空棧, 空則下溢;不空則作②);

②X=S(TOP),(退棧後的元素賦給X):

③TOP=TOP-1,結束(棧指針減1,指向棧頂)。

❺ 用C語言寫程序的時候層數太多會不會出問題我用義隆的單片機

會出現堆棧溢出
一般編譯器在編譯時候,會將全局變數以外的空間都作為堆棧使用,函數內聲明的局部變數、數組等,全部是放在堆棧里的。
每運行一個函數,編譯器還會統計這個函數用到了幾個寄存器,然後在函數運行前將寄存器壓棧,函數返回前出棧
嵌套太多了,一直在壓棧,沒有出棧,或者局部變數聲明太多,很快堆棧就溢出了。
這也是單片機調用遞歸函數時要小心再小心的原因。
我曾經用ARM7編寫程序時,由於全局變數太多了,保留堆棧空間太少造成過堆棧溢出

閱讀全文

與單片機棧溢出相關的資料

熱點內容
安卓如何傳輸圖片給蘋果 瀏覽:827
可編程式控制制器原理應用網路 瀏覽:585
社畜解壓是什麼意思 瀏覽:434
吉利博越用哪個app啊 瀏覽:511
西安單片機晶振電容 瀏覽:187
分地面積的演算法 瀏覽:177
安卓手機升級包後怎麼安裝 瀏覽:262
濟南壓縮餅干哪有賣 瀏覽:524
怎麼用rar解壓百度網盤 瀏覽:660
手機哪款解壓縮軟體好用 瀏覽:80
失控的演算法代碼 瀏覽:297
程序員說有人愛你怎麼回答 瀏覽:106
騰訊游戲安卓怎麼用ios登錄 瀏覽:759
石獅雲存儲伺服器 瀏覽:180
python滲透入門到精通 瀏覽:272
如何真機調試安卓進程 瀏覽:739
農行app怎麼交公共維修基金 瀏覽:667
python中字典增加元素 瀏覽:240
伺服器端渲染的數據怎麼爬 瀏覽:163
壓縮空氣噴射器 瀏覽:489