<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

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

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

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

  4

本文引用地址:http://dyxdggzs.com/article/201811/395096.htm

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

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

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

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

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

  StoreRfBit(0);

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

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

  if(Rf_bit_count >= RF_RAWBIT_LEN){

  Rf_frame_times++;

  StoreRfCompleteIdx();

  SetRfFrameComplete();

  }

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

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

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

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

1543555761907915.gif

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

  5

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

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

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

timg (1).gif

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

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

  uint8_t  Rx_buffer[RF_DATA_LEN];

  uint8_t  Rx_rawbit[RF_RAWDATA_LEN];

  uint16_t Rf_bit_count;

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

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

1543555836409141.jpg

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

  if(Rf_bit_count >= RF_RAWBIT_LEN){

  SetRfFrameComplete();

  }

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

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

  后記

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


上一頁(yè) 1 2 3 下一頁(yè)

關(guān)鍵詞: 數組

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>