RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

RT-Thread使用經(jīng)驗(yàn)分享:鏈表未初始化造成死機(jī)

冬至子 ? 來(lái)源:張世爭(zhēng) ? 作者:張世爭(zhēng) ? 2023-10-08 14:49 ? 次閱讀

前言
最近在開(kāi)發(fā)調(diào)試基于RT-Thread 的驅(qū)動(dòng)時(shí),遇到一個(gè)比較奇怪的死機(jī)問(wèn)題,后來(lái)經(jīng)過(guò)一步步排查,終于發(fā)現(xiàn)是驅(qū)動(dòng)的鏈表節(jié)點(diǎn)沒(méi)有初始化造成的死機(jī)

問(wèn)題分析
RT-Thread 的驅(qū)動(dòng)開(kāi)發(fā)完成后,通過(guò)編寫(xiě)串口 shell 測(cè)試命令,運(yùn)行命令后,觸發(fā)死機(jī)

由于當(dāng)前缺少單步的調(diào)試方法,只能通過(guò)增加LOG與打開(kāi)關(guān)閉部分軟件功能,一步步縮小范圍

在函數(shù)調(diào)用的入口,把某些關(guān)鍵的函數(shù)調(diào)用分別注釋掉驗(yàn)證,這樣逐步驗(yàn)證下來(lái),最終縮小到一個(gè)函數(shù),調(diào)用這個(gè)函數(shù)就觸發(fā)死機(jī)。

用到的軟件調(diào)試方法
(1)增加LOG,確認(rèn)代碼能執(zhí)行到哪些函數(shù),能執(zhí)行到哪些行

(2)通過(guò) #if 0 A_CODE #else B_CODE #endif 條件編譯的調(diào)試方法,大塊注釋部分代碼,確認(rèn)代碼執(zhí)行的路徑,縮小排查方向,確認(rèn)是執(zhí)行到哪個(gè)函數(shù)或模塊造成死機(jī)的

(3)通過(guò)對(duì)比代碼來(lái)確認(rèn)問(wèn)題,比如軟件正常工作過(guò),后來(lái)改動(dòng)死機(jī)了,大概率說(shuō)明是改動(dòng)造成的,所以可以通過(guò) git BCompare.exe 等代碼管理與比對(duì)工具,代碼回溯,兩份新舊代碼對(duì)比分析,逐步把排查范圍縮小,從代碼層面分析可能造成死機(jī)的原因

問(wèn)題分析
軟件調(diào)試有時(shí)候比較的簡(jiǎn)單,有時(shí)候會(huì)比較的復(fù)雜,由于這個(gè)驅(qū)動(dòng)移植來(lái)自其他系統(tǒng)的,數(shù)據(jù)結(jié)構(gòu)里面的成員比較的多,所以初步通過(guò)代碼對(duì)比工具如 BCompare 進(jìn)行代碼對(duì)比,發(fā)現(xiàn)了一點(diǎn)端倪:由于RT-Thread 暫時(shí)不支持 hash list(哈希鏈表),我把 hash list的功能實(shí)現(xiàn) 改為了 RT-Thread 的 list 替代,struct rt_list_node。

對(duì)比了軟件的其他改動(dòng)點(diǎn),雖然改動(dòng)部分較大,但軟件工作流程差不多,初步排查代碼沒(méi)有實(shí)質(zhì)性的差異

通過(guò)進(jìn)一步的排查并縮小范圍,終于發(fā)現(xiàn)了問(wèn)題點(diǎn):這個(gè)函數(shù)在 插入鏈表 的操作部分死機(jī)了!

通過(guò)代碼繼續(xù)網(wǎng)上找,發(fā)現(xiàn)這個(gè)包含 RT-Thread list 的數(shù)據(jù)節(jié)點(diǎn),是通過(guò) rt_malloc 申請(qǐng)的,并且沒(méi)有看到成員 list 使用 rt_list_init 初始化鏈表的操作

所以馬上確認(rèn)了問(wèn)題: 鏈表的節(jié)點(diǎn)沒(méi)有初始化造成的,通過(guò)增加 list 初始化,本以為立即解決了問(wèn)題,但是竟然依舊死機(jī)!

意外的BUG發(fā)現(xiàn):數(shù)據(jù)節(jié)點(diǎn)的鏈表的頭,也就是 鏈表 head 也沒(méi)有初始化,解決方法同上,需要初始化 鏈表的頭:使用 rt_list_init,這樣問(wèn)題得到解決

移植的代碼之前使用的 hashlist,聲明時(shí)即初始化了,不需要顯示的初始化,而RT-Thread list,必須初始化,否則把鏈表節(jié)點(diǎn)插入 鏈表頭部的時(shí)候,就會(huì)出現(xiàn) 野指針或空指針 訪問(wèn)成員的問(wèn)題,肯定會(huì)出問(wèn)題。

1.jpg

解決方法就是 增加鏈表初始化操作

1.jpg

問(wèn)題回顧
由于先前移植的樣板驅(qū)動(dòng)使用的是 hash list,造成移植后沒(méi)有初始化數(shù)據(jù)結(jié)構(gòu)的鏈表節(jié)點(diǎn),觸發(fā)了死機(jī)。所以驅(qū)動(dòng)移植時(shí),遇到鏈表時(shí),一定要注意 鏈表頭與鏈表節(jié)點(diǎn)的 鏈表初始化問(wèn)題

另一個(gè)注意點(diǎn):操作空指針的成員,異常信息里面,可能會(huì)提示 異常出在一個(gè) 較小的 內(nèi)存地址上。所以遇到死機(jī),并且發(fā)現(xiàn)死機(jī)的 內(nèi)存地址很小,可以往 空指針?lè)较蚺挪?/p>

RT-Thread 雙向循環(huán)鏈表的操作,由于使用的是【宏定義】,也就是鏈表操作函數(shù)本身沒(méi)有判空的操作,用戶(hù)需要有鏈表指針判空的操作。

訪問(wèn)一個(gè)空指針的結(jié)構(gòu)體成員,肯定會(huì)觸發(fā)內(nèi)存異常死機(jī)。 如 buffer->list 中的 list 為 RT_NULL,那么訪問(wèn) buffer->list->next 時(shí)候,list 中的 next 成員地址就是非法的內(nèi)存地址(小地址),就會(huì)出現(xiàn)異常死機(jī)

小結(jié)
鏈表操作需要謹(jǐn)慎,不只是要把 鏈表頭 申請(qǐng)為 全局的,而且每個(gè)鏈表的節(jié)點(diǎn),都是需要全局的。

注意鏈表節(jié)點(diǎn)會(huì)嵌入到一個(gè)復(fù)雜的數(shù)據(jù)結(jié)構(gòu)里面,并且使用動(dòng)態(tài)內(nèi)存申請(qǐng)的方式 創(chuàng)建,這是一定要注意不要漏下 鏈表成員的初始化。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 驅(qū)動(dòng)器
    +關(guān)注

    關(guān)注

    52

    文章

    8226

    瀏覽量

    146251
  • Shell
    +關(guān)注

    關(guān)注

    1

    文章

    365

    瀏覽量

    23356
  • RT-Thread
    +關(guān)注

    關(guān)注

    31

    文章

    1285

    瀏覽量

    40081
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    RT-Thread自動(dòng)初始化詳解

    我們知道,在寫(xiě)裸機(jī)程序時(shí),當(dāng)我們完成硬件初始化后,就需要在主函數(shù)中進(jìn)行調(diào)用。當(dāng)我們使用RT-Thread后,完全不需要這樣做了,我們可以將硬件等自動(dòng)初始化。 RT-Thread?自動(dòng)
    的頭像 發(fā)表于 06-25 21:38 ?1.1w次閱讀
    <b class='flag-5'>RT-Thread</b>自動(dòng)<b class='flag-5'>初始化</b>詳解

    RT-Thread內(nèi)核對(duì)象初始化鏈表組織方式

    最近在看RT-Thread內(nèi)核的源碼,內(nèi)核對(duì)象使用鏈表組織。
    發(fā)表于 06-02 09:48 ?738次閱讀
    <b class='flag-5'>RT-Thread</b>內(nèi)核對(duì)象<b class='flag-5'>初始化</b><b class='flag-5'>鏈表</b>組織方式

    RT-Thread qemu mps2-an385 bsp移植制作 :系統(tǒng)運(yùn)行篇

    前面已經(jīng)讓 RT-Thread 進(jìn)入了 entry 入口函數(shù),并且 調(diào)整 鏈接腳本,自動(dòng)初始化與 MSH shell 的符號(hào)已經(jīng)預(yù)留, 進(jìn)入了 RT-Thread初始化
    的頭像 發(fā)表于 11-14 12:27 ?827次閱讀
    <b class='flag-5'>RT-Thread</b> qemu mps2-an385 bsp移植制作 :系統(tǒng)運(yùn)行篇

    RT-Thread 踩坑記錄 - 初始化線程時(shí)使用局部變量

    前言為了不再CTRL+C,CTRL+V,修改,我開(kāi)始嘗試手敲代碼。RT-Thread線程可以靜態(tài)初始化,也可以動(dòng)態(tài)申請(qǐng)內(nèi)存的方式創(chuàng)建靜態(tài)初始化線程靜態(tài)初始化線程時(shí),線程結(jié)構(gòu)體與線程的棧
    發(fā)表于 05-13 18:40

    RT-thread初始化過(guò)程是怎樣進(jìn)行的

    RT-thread初始化過(guò)程是怎樣進(jìn)行的?擴(kuò)展補(bǔ)丁Sub和super的作用是什么?如何去使用它們呢?
    發(fā)表于 11-29 07:42

    如何對(duì)RT-Thread系統(tǒng)進(jìn)行初始化

    RT-Thread是如何啟動(dòng)的?如何對(duì)RT-Thread系統(tǒng)進(jìn)行初始化呢?
    發(fā)表于 11-30 07:54

    RT-Thread內(nèi)核學(xué)習(xí)資料匯總

    操作方法在內(nèi)核文件 object.c 中實(shí)現(xiàn)4、RT-Thread內(nèi)核對(duì)象初始化鏈表介紹  鏈表是一種數(shù)據(jù)結(jié)構(gòu),跟其他的結(jié)構(gòu)體類(lèi)似,初始化
    發(fā)表于 03-15 10:45

    RT-Thread自動(dòng)初始化機(jī)制簡(jiǎn)介

    RT-Thread 的時(shí)鐘管理以時(shí)鐘節(jié)拍為基礎(chǔ),時(shí)鐘節(jié)拍是 RT-Thread 操作系統(tǒng)中最小的RT-Thread 自動(dòng)初始化機(jī)制時(shí)鐘單位。RT-T
    發(fā)表于 04-06 18:08

    淺析RT-Thread中對(duì)象容器與雙鏈表的操作

    _Object_Info_Unknown] ={ /* 初始化對(duì)象容器 - 線程 */ {RT_Object_Class_Thread,_OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread
    發(fā)表于 05-18 14:23

    一文詳解RT-Thread自動(dòng)初始化

    在學(xué)RT-Thread時(shí),經(jīng)常能聽(tīng)到這個(gè)詞:自動(dòng)初始化。用起來(lái)也非常容易,一個(gè)宏就解決了,但是原理是什么呢?
    的頭像 發(fā)表于 07-21 10:17 ?7588次閱讀
    一文詳解<b class='flag-5'>RT-Thread</b>自動(dòng)<b class='flag-5'>初始化</b>

    RT-Thread 內(nèi)核學(xué)習(xí)筆記 - 內(nèi)核對(duì)象初始化鏈表組織方式

    RT-Thread 內(nèi)核學(xué)習(xí)筆記 - 內(nèi)核對(duì)象rt_objectRT-Thread 內(nèi)核學(xué)習(xí)筆記 - 內(nèi)核對(duì)象管理RT-Thread 內(nèi)核學(xué)習(xí)筆記 - 內(nèi)核對(duì)象操作APIRT-Threa...
    發(fā)表于 01-25 18:24 ?3次下載
    <b class='flag-5'>RT-Thread</b> 內(nèi)核學(xué)習(xí)筆記 - 內(nèi)核對(duì)象<b class='flag-5'>初始化</b><b class='flag-5'>鏈表</b>組織方式

    RT-Thread全球技術(shù)大會(huì):如何使用組件以及自動(dòng)初始化流程

    RT-Thread全球技術(shù)大會(huì):如何使用組件和自動(dòng)初始化流程 ? ? ? ? ? 審核編輯:彭靜
    的頭像 發(fā)表于 05-27 15:16 ?932次閱讀
    <b class='flag-5'>RT-Thread</b>全球技術(shù)大會(huì):如何使用組件以及自動(dòng)<b class='flag-5'>初始化</b>流程

    RT-Thread自動(dòng)初始化機(jī)制

    ??在分析之前首先查閱 RT-Thread 的官方文檔 [RT-Thread 自動(dòng)初始化機(jī)制](https://www.rt-thread.org/document/site
    的頭像 發(fā)表于 06-17 08:52 ?2634次閱讀
    <b class='flag-5'>RT-Thread</b>自動(dòng)<b class='flag-5'>初始化</b>機(jī)制

    rt-thread線程棧初始化參數(shù)分析

    RT-Thread 在線程初始化的代碼內(nèi)有一段初始化線程堆棧的代碼
    的頭像 發(fā)表于 08-14 16:50 ?1716次閱讀
    <b class='flag-5'>rt-thread</b>線程棧<b class='flag-5'>初始化</b>參數(shù)分析

    RT-Thread使用經(jīng)驗(yàn)分享:動(dòng)態(tài)申請(qǐng)的內(nèi)存清零造成死機(jī)

    最近在開(kāi)發(fā)調(diào)試基于RT-Thread 的程序時(shí),遇到一個(gè)比較奇怪的死機(jī)問(wèn)題,后來(lái)經(jīng)過(guò)一步步排查,終于發(fā)現(xiàn)是動(dòng)態(tài)內(nèi)存申請(qǐng)的數(shù)據(jù)結(jié)構(gòu)沒(méi)有清零引發(fā)的死機(jī)。
    的頭像 發(fā)表于 10-08 14:59 ?1029次閱讀
    <b class='flag-5'>RT-Thread</b>使用<b class='flag-5'>經(jīng)驗(yàn)</b>分享:動(dòng)態(tài)申請(qǐng)的內(nèi)存<b class='flag-5'>未</b>清零<b class='flag-5'>造成</b><b class='flag-5'>死機(jī)</b>
    RM新时代网站-首页