在進行產品開發或者軟件設計時,有沒有遇到過下面的這種情況:
程序本來運行的好好的,莫名其妙的就出現了bug,但是還找不到出現bug的規律?
已經驗證好的產品,到客戶那里突然出現了問題?
出現的bug總是莫名其妙,找不到規律,感覺像“幽靈”一般的存在?
增加了一行無關的代碼,程序就不能運行了?
其實,有的時候,問題原因會以一種微妙的方式影響代碼的存在,今天我們重點講解一下難以發現的、容易導致軟件問題的5種情況,以及所對應的應對措施。
01
堆棧溢出
肯定很多程序員都非常了解“堆棧溢出”這種情況。堆棧溢出可能會對數據或者指令造成破壞,從而影響程序的正確運行。 并且,發生堆棧溢出這種錯誤,在嵌入式設備程序中造成的影響比計算機中更大。通常有以下幾種原因:
1、嵌入式系統通常使用較少的RAM
2、通常沒有可依賴的虛擬內存(因為沒有磁盤)
3、基于RTOS任務的固件設計使用多個堆棧(每個任務一個),每個堆棧的大小必須足夠大,以確保不受唯一最壞情況堆棧深度的影響
4、中斷處理程序可能會嘗試使用這些堆棧 在進行相關測試的時候,有的時候堆棧溢出這種錯誤我們并不能測試出來,這就造成了:經過測試驗證的程序,到客戶處突然運行異常了。
為了避免發生堆棧溢出這種錯誤,我們可以通過自上而下的代碼控制流分析方法,來證明代碼是否會出現堆棧溢出錯誤。
避免措施:
1、確定好自己程序定義的堆棧的全部空間地址;
2、在臨近堆棧的位置,定義固定地址的數組或者數據;
3、在程序中實時檢查數組或者數據的值,若發現數據改變,證明發生了堆棧溢出,增加特殊的處理姿勢:如讓設備進入到特定的安全模式,或者輸出當前的PC地址等。
02
競爭條件
在程序運行過程中,大量的、無序的任務一直在運行,但是資源是有限的,兩個不同的任務之間可能就存在競爭資源的情況,由于兩個或者多個進程競爭使用不能被同時訪問的資源,使得這些進程有可能因為時間上推進的先后原因而出現問題,這叫做競爭條件。
條件競爭就是兩個或者多個進程或者線程同時處理一個資源(如全局變量、文件等)產生非預想的執行效果,從而產生程序執行流的改變,從而達到攻擊的目的。
防止條件競爭的方法如下:
1、采用某種保護機制來保護數據(如互斥體),確保只有進行修改的線程才能看到不變量被破壞時的中間狀態;
2、使用無鎖編程;
3、使用事務來處理更新,將數據和讀取都存儲到事務日志中,然后將之前的操作合并為一步,再進行提交。當數據被另一個線程修改后,或處理已經重啟的情況下,提交就會無法進行。
03
不可重入函數
首先需要區分什么是可重入什么是不可重入函數?
可重入函數:可重入函數可以由多個任務并發使用,而不必擔心數據錯誤
不可重入函數:不能由超過一個任務所共享,除非能確保函數的互斥(或者使用信號量,或者在代碼的關鍵部分禁用中斷)
一些常見的不可重入函數的情形:
函數中使用了靜態變量,無論是全局變量還是局部靜態變量
函數返回靜態變量
函數中調用了不可重入函數
函數體內使用了靜態的數據結構
函數體內調用了malloc()或者free()函數
函數體內調用了其他標準I/O函數
函數是singleton中的成員函數而且使用了不使用線程獨立存儲的成員變量
總得來說,如果一個函數在重入條件下使用了未受保護的共享資源,那么他就是不可重入的。
例如兩個函數func1和func2都是不可重入函數:對多線程條件下,操作系統會在func1還沒有執行完的情況下,切換到另一個線程中,那個線程可能再次調用func1,這樣狀態就錯了。
避免措施:
在每個庫或驅動程序模塊中創建并隱藏一個本質上不可重入的互斥鎖。將此互斥鎖的獲取作為操作整個模塊中使用的任何持久數據或共享寄存器的先決條件。
04
優先級翻轉
優先級翻轉是當一個高優先級任務通過信號量機制訪問共享資源時,該信號量已被一低優先級任務占有,因此造成高優先級任務被許多具有較低優先級任務阻塞,實時性難以得到保證。
比較經典的由于優先級翻轉造成的事故就是當年的火星探路者號,就由于,此處所說的,優先級反轉,而導致了內部執行邏輯出錯的bug。
在1997年7月4號發射后,在開始搜集氣象數據之后沒幾天,系統(無故)重啟了。后來,當然,被相關技術人員找到問題根源,就是,這個優先級反轉所導致的,然后修復了此bug。
解決措施:
1、優先級天花板
優先級天花板是當線程申請某資源時,把該線程的優先級提升到可訪問這個資源的所有線程中的最高優先級,這個優先級稱為該資源的優先級天花板。這種方法簡單易行,不必進行復雜的判斷,不管線程是否阻塞了高優先級線程的運行, 只要線程訪問共享資源都會提升線程的優先級。
2、優先級繼承
優先級繼承是當線程A申請共享資源Source時,如果共享資源Source正在被線程C使用,通過比較線程C與自身的優先級,如發現線程C的優先級小于自身的優先級, 則將線程C的優先級提升到自身的優先級,線程C釋放資源Source后,再恢復線程C的原優先級。這種方法只在占有資源的低優先級線程阻塞了高優先級線程時才動態的改變線程的優先級。
05
內存泄漏
內存泄漏(Memory Leak)是指程序中已動態分配的堆內存由于某種原因程序未釋放或無法釋放,造成系統內存的浪費,導致程序運行速度減慢甚至系統崩潰等嚴重后果。
解決措施: 當申請了動態區域,用完的時候一定要記得釋放(free),如果沒有釋放,那么這塊內存區域就將處于不可用狀態(就像占著茅坑不拉屎一樣),程序大了或運行久了就極有可能會導致內存的泄露(重啟一下就能解決90%的問題根源),同時我們在釋放的時候也要注意釋放的內存只能釋放一次,不要重復的釋放,有的時候代碼量會比較大,所以有可能會在不止一處地方進行了代碼的釋放操作。因為我們內存釋放了一次后,該內存區域就有可能用來做別的事了,如果這時候我們又再釋放一遍就很有可能會出現問題了。釋放完之后最好把指針指向空地址,避免下次再使用指針的時候出現地址的錯誤。
審核編輯:劉清
-
RAM
+關注
關注
8文章
1391瀏覽量
116705 -
中斷處理
+關注
關注
0文章
94瀏覽量
11190 -
RTOS
+關注
關注
24文章
838瀏覽量
120711 -
堆棧溢出
+關注
關注
0文章
9瀏覽量
8003
原文標題:不要以為莫名其妙的bug是玄學!介紹5個引起程序隱藏bug的原因以及預防措施。
文章出處:【微信號:精通單片機與嵌入式,微信公眾號:精通單片機與嵌入式】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
rtthread_studio使用lwip軟件包變異報錯是什么原因導致的?
“碰一下”支付背后的4G技術
支付寶發布新一代AI視覺搜索“探一下”
智多晶EDA工具HqFpga軟件實用小功能

什么情況下無功補償電容器會出現損壞

評論