嵌入式軟件bug從哪里來,到哪里去

摘要:軟件從來不是一次就能完美的,需要以包容的眼光看待它的殘缺。那問題究竟為何產生,如何去除呢?

1、軟件問題從哪來

軟件缺陷問題千千萬萬,主要是需求、實現、和運行環境三方面。

1.1 需求描述偏差

客戶角度的描述,在經過業務對接、產品經理的轉述,最終呈現的軟件需求可能已經偏離了原始的述求,開發人員基于自身經驗的理解偏差,開發過程缺乏有效的溝通及監督,導致最終的軟件功能與客戶的核心訴求存在偏差。

1.2 異常處理機制不完善

嵌入式軟件必定是運行在特定的硬件設備,硬件本身或環境問題等特殊干擾,開發人員因經驗不足缺乏風險評估,面對電腦是無法全方位猜測、模擬各種異常環境下的差異,最終導致設備在特定場景下運行異常。

1.3 軟件開發能力不足

嵌入式系統的復雜度與開發人員的能力矛盾,導致軟件本身的邏輯存在缺陷。

2、軟件開發與軟件問題

關于軟件bug的來源,排除不可控的外界因素,與軟件開發人員相關,或者開發人員可以減少問題的發生的可能,從軟件開發角度解決的方案如下:

2.1 重視需求分析

軟件開發就是寫程序,并設法使之運行,這是個錯誤的想法。軟件結果與客戶期望不一致,需求問題不全是軟件開發的鍋。大多數情況下客戶的原始述求不會直接到軟件開發,軟件開發沒法去反訴找客戶確認,只能通過軟件的實現形式去甄別不合理的,或者針對客觀環境、研發團隊的基礎去評估風險。

比如客戶要求可以設備可以定時1秒采集一次溫度,精度要求0.0001攝氏度;或者要求數據采集持續采集24h后,每天12:00準點TCP上報后臺服務器。這就需要考慮溫度傳感器的精度、RTC喚醒以及TCP聯網時間、24小時采樣數據的存儲。如果硬件資源或者客觀環境無法實現,盲目承諾客戶,或者開始編碼,最終結果可想而知。

軟件開發是個人的任務,但開發前多溝通確認,進行風險評估反饋,減少開發的無用功,也是對開發人員的基本要求。

2.2 積累行業經驗

嵌入式產品都是針對某個細分行業,見多識廣,才能預判可能出現的異常,開發階段有針對性的去處理,或者提前告知使用者去規避。有時候經驗比技術能力重要。

2.3 提高開發水平

軟件開發水平,首先是個人能力,熟悉軟件SDK的應用,相關的操作系統、設計模式、調試方法等。軟件開發能力大多數情況下決定軟件質量和可維護性,這是個長期學習提高的過程,如果一定要提供捷徑,那就是多閱讀優秀的開源代碼。

2.4 先設計再編碼

軟件開發不能隨心所欲,先明確方案和大概的實現流程,胸有成竹,然后再開始編碼,完善細節。這理論沒毛病,但真正執行起來卻比較難,大多數情況下都只在乎軟件出結果,而實際上方案不合理,后期修修補補更浪費時間。如果制度和時間不允許,個人在紙上畫畫框圖和結構,先構思再開發也能彌補,起碼不至于南轅北轍。

2.5 編碼規范

編碼規范是軟件開發團隊合作的標準,嵌入式行業可以參考“華為技術C語言編程規范”,但實際開發過程,和前面的先設計再編碼一樣,各種不可控因素,比如項目進度壓力和開發者水平與認知的差異,導致有編碼規范卻無法嚴格執行。隨著軟件工程規模的擴大,軟件交期、代碼同步、重構或交接,其風險也逐漸放大。存在編碼規則并不能解決問題,只有強制執行才有意義。

2.6 代碼缺陷靜態檢查與單元測試

軟件質量是項目成敗的關鍵點之一,在開發周期有限,人力資源不足的情況下,使用工具實現代碼自動掃描,分析出潛在隱患點,可從源頭減少軟件bug,比如cppCheck、PC-lint等,實現代碼自動靜態分析,或者人工視檢,有效規避簡單的軟件風險。

如果可能,最佳的選擇是單元測試,單元測試比可交付成果本身更重要,文檔注釋不全時,單元測試就是設計文檔;單元測試定義的API和用法,以及可能的使用風險點,就是最佳的參考范例;不足100%的覆蓋率就是玩忽職守,開發人員應該全權負責測試自己造出的產品。依靠后期的黑盒測試發現問題,其消耗的人力物力,是編寫單元測試的幾倍,而且單元測試可以反復的自動測試。不過這種情況更多的是存在于開發理論中。

3、前期減少問題

軟件問題的解決,有些不是個人能解決的,需要協調溝通,或者與研發團隊的整體風格、制度有關。個人能決定的是軟件具體邏輯,這也是體現個人技術能力的重點。

3.1 C語言基礎

1、多看優秀代碼,學習其技巧。

2、使用帶參數檢測的接口,比如優先選擇snprintf,少用sprintf,其它str前綴的如strncmp也是,但要明白這類接口和memcmp區別。不同的編譯器表現不一致,平時也要多關注。

在GCC中編譯運行(設備):

char str[5];int ret = snprintf(str, 3, "%s", "abcdefg");//ret = 7 ,str = abchar str[99];int ret = snprintf(str, 99, "%s", "abcdefg");//ret = 7 ,str = abcdefg

注:snprintf的返回值為字符串的長度,且寫入的字符串后面帶有‘\0’結束符。

在VC中編譯運行:

char str[5];int ret = snprintf(str, 3, "%s", "abcdefg");//ret = -1 ,str = abc  [后面不會自動補\0結束符]

3、注意函數返回類型,避免類型強制轉換導致調用判斷異常,有些編譯器對隱示類型轉換直接報錯,因為它確實存在風險。

4、合理的使用sizeof、struct、union、weak等關鍵字,增加代碼的可讀性和可擴展性。

5、參數使用前,如數組小標,指針變量使用前必須先判斷是否合法。

6、浮點數不能直接進行==和!=比較,等等,這些細節太多,可以參考《C陷阱與缺陷》。

7、講的都會,說的都對,但真實際寫代碼,就容易各種小問題,主要還是態度問題,缺乏自我檢查、自測的步驟,依靠測試發現bug去驅動研發調試修復是大忌。
?

3.2 動態內存

1、盡量做到申請與釋放在同一個函數,申請內存后,先判斷是否申請成功,再進行其它操作。

2、內存申請與釋放之間有特殊情況return,要注意釋放。

3、釋放結構體指針前,注意該變量內部是否還有指針變量動態申請空間,先釋放內部,再釋放外部。

4、關于內存申請與釋放,或使用越界是C語言的劣勢,如果設備堆空間足夠大,可以在申請時額外多申請固定空間,記錄申請函數、長度、并在首尾標記,后續釋放時檢查內存區首尾標記是否被覆蓋;或者查詢是哪些函數申請的內存始終沒有被釋放。

3.3 跨平臺問題

1、使用系統API前先判斷自身傳入參數的有效性和范圍等是否符合要求,一般系統API是庫文件,使用錯誤更難發現問題。

2、針對不同的平臺常用的接口,務必增加適配層隔離,便于調試和后續移植。比如有的平臺中斷(SDK提供的中斷回調不一定是硬件中斷)不支持串口日志。

3.4 RTOS系統特性

1、多任務的競爭,在RTOS系統中,需要注意全局函數、全局變量的使用,避免互相競爭影響,對公共函數盡量做到可重入設計。

2、中斷與任務的調度關系。

3、合理分配任務棧空間和消息隊列的深度,函數內部盡量少用大數組。

3.5 個人素養

軟件編碼完成,不是能編譯就收工了,其功能是否符合預期,開發人員自己檢查是最高效的,很多問題都是開發不仔細,或者很簡單的C基礎應用錯誤,這不是技術問題而是心態。可以多看看開源代碼,或者《C專家編程》等。

4、后期解決問題

如果軟件問題不可避免,該如何去修復解決呢?

一般來說100%出現的問題都比較容易解決,找到相關代碼仔細檢查或者加點日志就能發現問題。難處理的是小概率出現的問題,穩定復現它就是成功的一半。

4.1 問題復現

穩定復現問題才能快速對問題進行定位、解決以及驗證,如何提高復現的概率?

1、模擬復現條件問題只在特定的條件下出現,對于依賴外部輸入的條件難以滿足,可以考慮程序里預設直接進入對應狀態,或者軟件內部進行極端的壓力測試。

2、提高相關代碼執行頻率,進行某個操作才可能出現異常,人工持續操作,或者軟件頻繁執行相應的功能,提高問題點的執行頻率,加快復現速度。

3、增大測試樣本量 個別樣機難出現,如果條件允許,可以使用多個設備同時進行測試。一般情況下試產就是為了發現這類問題。

4.2 問題定位

縮小排查范圍,確認引入問題的函數或代碼片段。

1、打印日志 日志是最直接、簡單的調試方法,在問題的可疑點增加日志輸出,以此來追蹤程序執行流程以及關鍵變量的值,觀察是否與預期相符。

2、版本回退使用版本管理工具時可以通過不斷回退版本,驗證前面版本的情況,定位首次引入該問題的版本,針對該版本的改動進行排查。

3、二分注釋“二分注釋”類似二分查找法的方式注釋掉部分代碼,以此判斷問題是否由注釋掉的這部分代碼引起。具體為將與問題不相干的部分代碼注釋掉一半,看問題是否解決,未解決則注釋另一半,如果解決則繼續將注釋范圍縮小一半,以此類推逐漸縮小問題的范圍,確定是哪一塊代碼導致這個問題。

4、硬件協助,借助示波器、邏輯分析儀分析波形,必要時也請硬件協助分析;問題樣機與正常樣機的主控對調,看問題是否隨芯片走。尤其是涉及驅動方面的問題,比如充電、中斷、復位、外設通信調試異常時。

5、仿真調試 在線調試可以起到和打印LOG類似的作用,適合排查程序崩潰類的BUG,當程序陷入異常中斷候可以直接STOP查看call stack以及內核寄存器的值,快速定位問題點,不過這需要硬件支持。

6、三板斧使用最多的是前面三種方法,這三板斧足以應付大部分業務邏輯問題;偶爾請硬件協助解決驅動問題,日常開發中的問題都能解決。個別系統層面或者架構不合理導致的深沉問題,要么花時間死磕coredunmp,要么聯系原廠FAE協助,一般芯片方案商都提供技術支持。

4.3 問題修復與回歸測試

1、縮小范圍確定問題代碼,再排查具體的函數,修復問題點

2、有些問題屬于架構層面,比如和RTOS相關的競爭關系,這種就無法定位到具體問題代碼點,只能在宏觀上依靠經驗或操作系統理論去解決

3、解決后需要進行回歸測試,確認問題是否不再出現,也要確認修改不會引入其他新問題。

4.4 復盤

1、一般情況下最后發現原因都是很簡單的幾句話,比如數據越界或者循環體多執行一次,看起來都是很簡單的基礎用法,因為一句錯誤可能需要幾周時間來發現解決,為什么當初寫錯而且沒檢查發現呢?

2、總結問題產生的原因及解決方法,今后如何防范,對其他平臺否值得借鑒,做到舉一反三,從失敗中吸取經驗。

5、心得

業務指示開發、測試驅動開發,這一荒謬方法論,體現在部門合作與職責不清,整體就是效率低下、互相推諉,在這樣的環境下開發軟件也很累。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/710959.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/710959.shtml
英文地址,請注明出處:http://en.pswp.cn/news/710959.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PSO-CNN-LSTM多輸入回歸預測|粒子群算法優化的卷積-長短期神經網絡回歸預測(Matlab)——附代碼數據

目錄 一、程序及算法內容介紹: 基本內容: 亮點與優勢: 二、實際運行效果: 三、算法介紹: 四、完整程序數據分享下載: 一、程序及算法內容介紹: 基本內容: 本代碼基于Matlab平臺…

5 局域網基礎(3)

1.AAA 服務器 AAA 是驗證、授權和記賬(Authentication、Authorization、Accounting)3個英文單詞的簡稱,是一個能夠處理用戶訪問請求的服務器程序,提供驗證授權以及帳戶服務,主要目的是管理用戶訪問網絡服務器,對具有訪問權的用戶提供服務。AAA服務器通常…

Java TCP文件上傳案例

文件上傳分析 【客戶端】輸入流,從硬盤讀取文件數據到程序中。【客戶端】輸出流,寫出文件數據到服務端。【服務端】輸入流,讀取文件數據到服務端程序。【服務端】輸出流,寫出文件數據到服務器硬盤中。 基本實現 服務端實現 pu…

【二分查找】樸素二分查找

二分查找 題目描述 給定一個 n 個元素有序的(升序)整型數組 nums 和一個目標值 target ,寫一個函數搜索 nums 中的 target,如果目標值存在返回下標,否則返回 -1。 示例 1: 輸入: nums [-1,0,3,5,9,12], target 9…

網絡編程:基于TCP和UDP的服務器、客戶端

1.基于TCP通信服務器 程序代碼&#xff1a; 1 #include<myhead.h>2 #define SER_IP "192.168.126.121"//服務器IP3 #define SER_PORT 8888//服務器端口號4 int main(int argc, const char *argv[])5 {6 //1.創建用于監聽的套接字7 int sfd-1;8 sf…

MYSQL C++鏈接接口編程

使用MYSQL 提供的C接口來訪問數據庫,官網比較零碎,又不想全部精讀一下,百度CSDN都是亂七八糟的,大部分不可用 官網教程地址 https://dev.mysql.com/doc/connector-cpp/1.1/en/connector-cpp-examples-connecting.html 網上之所以亂七八糟,主要是MYSQL提供了3個接口兩個包,使用…

C++ //練習 10.9 實現你自己的elimDups。測試你的程序,分別在讀取輸入后、調用unique后以及調用erase后打印vector的內容。

C Primer&#xff08;第5版&#xff09; 練習 10.9 練習 10.9 實現你自己的elimDups。測試你的程序&#xff0c;分別在讀取輸入后、調用unique后以及調用erase后打印vector的內容。 環境&#xff1a;Linux Ubuntu&#xff08;云服務器&#xff09; 工具&#xff1a;vim 代碼…

Flask g對象和插件

四、Flask進階 1. Flask插件 I. flask-caching 安裝 pip install flask-caching初始化 from flask_cache import Cache cache Cache(config(CACHE_TYPE:"simple" )) cache.init_app(appapp)使用 在視圖函數上添加緩存 blue.route("/") cache.cached(tim…

django5生產級部署和并發測試(開發者服務器和uvicorn服務器)

目錄 1. 創建django項目2. 安裝壓力測試工具3. 安裝生產級服務器uvicorn4. 多進程部署 1. 創建django項目 在桌面創建一個名為django_test的項目&#xff1a; django-admin startproject django_test然后使用cd命令進入django_test文件夾內&#xff0c;使用開發者服務器運行項…

前端架構: 腳手架包管理工具之lerna的全流程開發教程

Lerna 1 &#xff09;文檔 Lerna 文檔 https://www.npmjs.com/package/lernahttps://lerna.js.org [請直達這個鏈接] 使用 Lerna 幫助我們做包管理&#xff0c;并不復雜&#xff0c;中間常用的命令并不是很多這里是命令直達&#xff1a;https://lerna.js.org/docs/api-referen…

掌匯云 | FBIF個性化票務系統,展會活動數據好沉淀

“把票全賣光&#xff01;賣到一票難求&#xff0c;現場座無虛席。” 賣票人和買票人可能永遠不在一個頻道上。 2022年辦活動&#xff0c;就是一個字&#xff0c;搏&#xff01;和“黑天鵝”趕時間&#xff0c;能不能辦不由主辦方說了算。這種情況在2023年得到了改善&#xff…

【字典樹】【KMP】【C++算法】3045統計前后綴下標對 II

作者推薦 動態規劃的時間復雜度優化 本文涉及知識點 字符串 字典樹 KMP 前后綴 LeetCode:3045統計前后綴下標對 II 給你一個下標從 0 開始的字符串數組 words 。 定義一個 布爾 函數 isPrefixAndSuffix &#xff0c;它接受兩個字符串參數 str1 和 str2 &#xff1a; 當 st…

C++——內存管理(new和delete)詳解

目錄 C/C內存管理 案例&#xff1a;變量在內存中到底會在哪&#xff1f; New和delete Operator new和operator delete函數 New和delete的原理 對內置類型 對自定義類型 定位new New/delete和malloc/free的區別 C/C內存管理 C/C內存管理分布圖&#xff1a;&#xff08;從…

項目案例:圖像分類技術在直播電商中的應用與實踐

一、引言 在數字化浪潮的推動下&#xff0c;電商行業迎來了一場革命性的變革。直播電商&#xff0c;作為一種新興的購物模式&#xff0c;正以其獨特的互動性和娛樂性&#xff0c;重塑著消費者的購物習慣。通過實時的直播展示&#xff0c;商品的細節得以清晰呈現&#xff0c;而互…

matlab:涉及復雜函數圖像的交點求解

matlab&#xff1a;涉及復雜函數圖像的交點求解 在MATLAB中求解兩個圖像的交點是一個常見的需求。本文將通過一個示例&#xff0c;展示如何求解兩個圖像的交點&#xff0c;并提供相應的MATLAB代碼。 畫出圖像 首先&#xff0c;我們需要繪制兩個圖像&#xff0c;以便直觀地看…

【JavaEE】_HttpServletResponse類

目錄 1. 核心方法 2. 關于setStatus(400)與sendError 2.1 setStatus(400) 2.2 sendError 3. setHeader方法 4. 構造重定向響應 4.1 使用setHeader和setStatus實現重定向 4.2 使用sendRedirect實現重定向 本專欄已有文章介紹HttpServlet和HttpServletRequest類&#…

仿真科普|CAE技術賦能無人機 低空經濟蓄勢起飛

喝一杯無人機送來的現磨熱咖啡&#xff1b;在擁堵的早高峰打個“空中的士”上班&#xff1b;乘坐水陸兩棲飛機來一場“陸海空”立體式觀光……曾經只出現在科幻片里的5D城市魔幻場景&#xff0c;正逐漸走進現實。而推動上述場景實現的&#xff0c;就是近年來越來越熱的“低空經…

前端開發——ElementUI組件的使用

文章目錄 1. Tabs標簽頁2. 單選框 el-radio3. 復選框 el-checkbox4. 下拉框 el-select5. 表格 el-table6. 對話框 el-dialog7. 文字提示 el-tooltip8. 抽屜 el-drawer 1. Tabs標簽頁 <template><el-tabs v-model"activeName" tab-click"handleClick&q…

python學生成績管理系統(期末課程作業)

功能介紹 平臺采用B/S結構&#xff0c;后端采用主流的Python語言進行開發&#xff0c;前端采用主流的Vue.js進行開發。本學期的期末作業。開發了1周 功能包括&#xff1a;成績管理、學生管理、課程管理、班級管理、用戶管理、日志管理、系統信息模塊。 源碼地址 https://gi…

c語言求簡單交錯序列前N項和

本題要求編寫程序,計算序列 1 - 1/4 1/7 - 1/10 ... 的前N項之和。 輸入格式: 輸入在一行中給出一個正整數N。 輸出格式: 在一行中按照“sum S”的格式輸出部分和的值S&#xff0c;精確到小數點后三位。題目保證計算結果不超過雙精度范圍。 輸入樣例: 10輸出樣例: su…