<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 牛人業(yè)話 > 數(shù)組越界真可怕,莫名就闖到了別人家

          數(shù)組越界真可怕,莫名就闖到了別人家

          作者:天雷君 時(shí)間:2018-11-30 來源:電子產(chǎn)品世界 收藏

            4

          本文引用地址:http://www.ex-cimer.com/article/201811/395096.htm

            筆者曾經(jīng)在《天靈靈地靈靈,遙控為何會失靈》一文中講述過報(bào)文解析程序的一部分原理和設(shè)計(jì),

            “射頻位到數(shù)據(jù)位采用了曼徹斯特編碼形式,以射頻位01表示數(shù)字位1,以射頻位10表示數(shù)字位0,BCM采用上升沿觸發(fā)中斷的方式,根據(jù)相鄰兩個(gè)上升沿之間的時(shí)間間隔來賦值射頻位。BCM根據(jù)遙控報(bào)文的格式提取出“數(shù)據(jù)場”中的射頻位位流,然后進(jìn)行曼徹斯特解碼,計(jì)算出數(shù)據(jù)位位流,進(jìn)而提取出字節(jié)形式的數(shù)據(jù)。。。。相鄰兩個(gè)上升沿的間隔取值只可能為2T、3T、4T,T為射頻位位寬?!?/p>

            前文所述“把數(shù)據(jù)位0或1這個(gè)‘大象’放到前面打開的‘冰箱’里”,指的就是賦值射頻位的過程,

            如果是2T,執(zhí)行StoreRfBit(0); StoreRfBit(1);

            如果是3T,執(zhí)行StoreRfBit(1); StoreRfBit(0); StoreRfBit(1); 或者StoreRfBit(0); StoreRfBit(1);

            StoreRfBit(0);

            如果是4T,執(zhí)行StoreRfBit(1); StoreRfBit(0); StoreRfBit(0); StoreRfBit(1);

            遙控報(bào)文的格式非常規(guī)整,能夠很容易地找到數(shù)據(jù)場的第一位,然后次序收完數(shù)據(jù)場的最后一位,本不該出現(xiàn)接收報(bào)文失敗的問題。既然無法通過分析代碼找出bug,那就只好祭出“調(diào)試大法”了。繼續(xù)添加測試語句:

            if(Rf_bit_count >= RF_RAWBIT_LEN){

            Rf_frame_times++;

            StoreRfCompleteIdx();

            SetRfFrameComplete();

            }

            灑家這次沒有吝惜RAM,開了個(gè)足以存儲好幾條報(bào)文射頻位位寬數(shù)據(jù)的輪轉(zhuǎn)型大,在判斷接收到一幀完整的報(bào)文語句那里存儲完整報(bào)文最后一個(gè)數(shù)據(jù)位在輪轉(zhuǎn)型大中的下標(biāo)位置,設(shè)置斷點(diǎn),運(yùn)行到斷點(diǎn)位置后,便可以從這個(gè)下標(biāo)往前搜索,看看之前幾個(gè)報(bào)文的射頻位位寬數(shù)據(jù)是否有什么異常。

            聰明的讀者肯定已經(jīng)搶先一步意識到了,射頻位位寬沒有出現(xiàn)任何異常。報(bào)文頭很規(guī)則,數(shù)據(jù)場很整齊,報(bào)文尾部也很利落。

            總之,所有的射頻位數(shù)據(jù)安安靜靜地等待在時(shí)間的無涯荒野里,沒有早一步,也沒有晚一步,我遇上了,卻沒有輕輕地說一句:哦,原來你也在這里呵!

            灑家揉了揉因?yàn)榭磾?shù)據(jù)看得有些發(fā)脹的眼睛,緩緩走到窗臺前,瞇縫起眼睛,打量了一下遠(yuǎn)處籠罩在一片蜃氣之中的青山。每每遇到難解的問題,灑家總要到窗臺陽光的沐浴中,眺望一下遠(yuǎn)處的山,讓腦袋放空,然后閉上眼睛,靜下心來,等著靈感不請自來。

          1543555761907915.gif

            中央空調(diào)沙沙的換氣聲音、同事的竊竊私語聲不時(shí)入耳,我在心里不斷回憶著有限的職業(yè)生涯里遇到的一個(gè)個(gè)bug,同時(shí)盤算著當(dāng)前程序可能的缺陷。報(bào)文格式的分段解析肯定沒問題,射頻位位寬的判斷也沒問題,射頻位的賦值也沒問題,想來都沒有問題,這個(gè)bug隱藏地夠深的。

            5

            還得調(diào)試!行文至此,我不禁懷疑起了自己的智商,為什么基本上所有難題的解決都是靠調(diào)試解決的?沒有一次是靈光電閃,看代碼直搗黃龍,找出bug的?

            被這個(gè)難題耗損了大半豪氣的我,老老實(shí)實(shí)地開始調(diào)試起來。為了定位bug,筆者特意修改了程序結(jié)構(gòu),之前的程序是邊接收邊解析,實(shí)時(shí)性固然好,但是接收了幾個(gè)數(shù)據(jù)便解析,不利于調(diào)試,所以改為收到兩三條報(bào)文后,再集中進(jìn)行解析。

            灑家看代碼找bug的本事沒有,設(shè)計(jì)調(diào)試方案找bug的能力還是有的。修改程序之后,調(diào)試下來,問題就慢慢浮上水面了。程序解析出報(bào)文頭部,進(jìn)入數(shù)據(jù)場之后,在賦值射頻位的過程中,結(jié)果出現(xiàn)了Rf_bit_count從288累加到33的情形?。?!

          timg (1).gif

            奇怪了,288累加一下應(yīng)該是289,怎么就變成33了?莫非1+1不等于2了不成?!!此處肯定有蹊蹺,灑家打眼一瞧,馬上看出了一點(diǎn)端倪,289和33正好差了一個(gè)256,就好像是把向高字節(jié)的進(jìn)位吃掉了一般。問題開始變得有趣了!

            Rf_bit_count是個(gè)16位的數(shù)據(jù),好像突然變成了8位數(shù)據(jù),顯然,它的高位字節(jié)發(fā)生了不為人知的變化!寫過多年代碼的灑家,立馬想到了是和Rf_bit_count臨近空間的數(shù)據(jù)搞的鬼,回到定義位置一看,

            uint8_t  Rx_buffer[RF_DATA_LEN];

            uint8_t  Rx_rawbit[RF_RAWDATA_LEN];

            uint16_t Rf_bit_count;

            一切都了然了,Rf_bit_count挨著Rx_rawbit這個(gè)數(shù)組,肯定是Rx_rawbit這個(gè)數(shù)組搞的事,這個(gè)數(shù)組越了界,就會改變Rf_bit_count的數(shù)據(jù),下面就簡單了,看看是不是這回事!

            我飛速地在紙上算了一下,當(dāng)Rf_bit_count=288時(shí),右移三位為36,Rf_rawbyte_idx =36時(shí),Rx_rawbit數(shù)組正好越界,由于Rf_bit_count的位置正好在Rx_rawbit之后,而且所使用的處理器是大端模式,大端方式將高位存放在低地址,小端方式將低位存放在低地址。

          1543555836409141.jpg

          所以,Rf_bit_count的高字節(jié)正好挨著Rx_rawbit數(shù)組,肯定是對Rx_rawbit[36]賦值為0了,導(dǎo)致Rf_bit_count本來是1的高字節(jié)變成了0,于是289就變成了33,這樣一來,判斷接收到一條完整報(bào)文的語句里的if語句里的條件肯定是false了,于是,好好的一幀數(shù)據(jù)就這樣被漏掉了。

            if(Rf_bit_count >= RF_RAWBIT_LEN){

            SetRfFrameComplete();

            }

            當(dāng)然,細(xì)心的讀者可能會比較奇怪,只需要接收288個(gè)射頻位,為什么Rf_bit_count還會累加到289呢?

            這是因?yàn)?,最后一個(gè)數(shù)據(jù)位可能是1也可能是0,最后統(tǒng)計(jì)到的射頻位寬可能是2T、3T或者4T,它們執(zhí)行的Rf_bit_count是不一樣的,有時(shí)正好統(tǒng)計(jì)到288,那自然萬事大吉,可以接收到報(bào)文,可是有時(shí)就會超過288,如前所述,這時(shí)它的高字節(jié)就有可能會被Rx_rawbit[36]吃掉,這就接收不到報(bào)文了。

            后記

            筆者學(xué)過一段時(shí)間的Java,Java對數(shù)組進(jìn)行了一定的安全處理,在運(yùn)行期間會自動(dòng)判斷數(shù)組下標(biāo)是否越界,當(dāng)時(shí)看的灑家羨慕得不得了。在計(jì)算機(jī)的世界里,C語言飽經(jīng)滄桑,年頭太老了,這種優(yōu)異的特性顯然指望不上,我等嵌入式工程師只能擦亮慧眼,始終保持警惕,要知道:數(shù)組越界真可怕,莫名就闖到了別人家。


          上一頁 1 2 3 下一頁

          關(guān)鍵詞: 數(shù)組

          評論


          相關(guān)推薦

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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();