博客專欄

        EEPW首頁 > 博客 > 斷言不是錯誤!

        斷言不是錯誤!

        發(fā)布人:魚鷹談單片機(jī) 時間:2022-01-21 來源:工程師 發(fā)布文章

        斷言機(jī)制估計很多道友都用過,在 ST 的標(biāo)準(zhǔn)庫中,經(jīng)常可以看到它的身影:

        1.png

        它的實現(xiàn)方式也是非常簡單的,就是通過 USE_FULL_ASSERT 宏進(jìn)行控制:

        2.png

        如果斷言失敗,就會執(zhí)行 assert_failed 函數(shù),一般實現(xiàn)函數(shù)如下:

        void assert_failed (uint8_t* file, uint32_t line)

        {

          static char buff[128];  

          sprintf (buff,"%s,%d", file, line);

          __breakpoint(0);

        }

        當(dāng)然這里的 sprintf 函數(shù)也常常使用 printf 代替,這樣就可以直接通過串口打印出來了,而魚鷹這個在沒有串口的情況下,可以通過內(nèi)存 buff 顯示出來,比較方便在線調(diào)試。

        而 __breakpoint(0) 一般由死循環(huán) while(1) 代替,而魚鷹覺得 while(1) 不夠好,因為斷言失敗后,可能很久你才能發(fā)現(xiàn)而進(jìn)入該死循環(huán),而使用  __breakpoint 可以讓你在 在線調(diào)試 模式下,立刻停止程序運行,從而可以快速定位問題。

        不管哪種實現(xiàn)方式,斷言失敗的結(jié)果一般只有暫停程序了,類似 linux 內(nèi)核的 panic 。

        而這是設(shè)計者希望看到的,但有些開發(fā)者認(rèn)為不應(yīng)該這樣,因為程序一旦死循環(huán),如果開啟了看門狗,會導(dǎo)致整個程序復(fù)位,對于產(chǎn)品而言,復(fù)位是很嚴(yán)重的 BUG 。

        “我不希望我的產(chǎn)品復(fù)位,所以請修改你的代碼,不讓他產(chǎn)生斷言失敗,可以嗎?”

        不可以。

        斷言本身不是錯誤,它只是發(fā)現(xiàn)你程序的 BUG ,進(jìn)而提醒你。

        斷言失敗,往往是很嚴(yán)重的問題,嚴(yán)重到這段代碼或功能無法正常執(zhí)行,所以你修改的地方應(yīng)該是調(diào)用者,而不是產(chǎn)生斷言的代碼,請不要顛倒主次,否則沒有從根本上解決問題。

        就比如最上面的 GPIO 外設(shè)指針檢查斷言部分,如果調(diào)用者傳入一個非 GPIO 的指針進(jìn)入函數(shù),從而產(chǎn)生斷言失敗,那么你會選擇關(guān)閉斷言機(jī)制還是說檢查你的代碼是否存在問題呢?

        當(dāng)然是后者。

        所以,如果產(chǎn)生了斷言失敗的情況,請不要慌,不要認(rèn)為這是一種錯誤,而應(yīng)該根據(jù)斷言失敗的位置,定位斷言失敗的根本原因,而不是試圖通過關(guān)閉斷言的方式讓程序繼續(xù)運行下去,這只會讓你的程序運行得更糟糕,同時也更難定位問題。

        *博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。



        關(guān)鍵詞: 單片機(jī)

        相關(guān)推薦

        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 金沙县| 西乌珠穆沁旗| 海丰县| 兖州市| 德庆县| 勃利县| 体育| 肇东市| 上饶市| 桂阳县| 富宁县| 正安县| 托里县| 新闻| 宁蒗| 堆龙德庆县| 克东县| 固安县| 札达县| 揭东县| 绥滨县| 垣曲县| 赫章县| 潜山县| 定州市| 德阳市| 通榆县| 攀枝花市| 义乌市| 仲巴县| 四子王旗| 云南省| 新和县| 浮梁县| 南充市| 新源县| 金平| 密云县| 涞源县| 鱼台县| 东明县|