1情景
售后 : X工,現(xiàn)場出大事了,今天升級(jí)的程序跑著跑著就掛了!現(xiàn)在整個(gè)產(chǎn)線都等著這個(gè)設(shè)備恢復(fù),能安排個(gè)人過來支援下嗎?
bug菌 : my god !別慌,我問一下負(fù)責(zé)的A工。
bug菌 : 喂,A工,昨天升級(jí)的程序有問題,程序卡死,售后在現(xiàn)場你聯(lián)系一下,支援他一波,順便把程序發(fā)送給我一份,一起看看!
A工 : 啊,還有這種事,程序沒改什么呀,行,我跟售后聯(lián)系一下。
經(jīng)過一番折騰,發(fā)現(xiàn)由于程序測試不到位,導(dǎo)致了一個(gè)強(qiáng)制類型轉(zhuǎn)化引發(fā)的進(jìn)入異常,這里就分享給大家。
2bug演示
這是一個(gè)老項(xiàng)目,采用stm32F4芯片為主控,由于硬件限制而客戶又不愿意花大價(jià)錢改造,所以程序架構(gòu)等等都沒有再大動(dòng)作,由于通信上的傳輸和解析都是字節(jié)流,一些小的需求都只是在原來的通信架構(gòu)上把4個(gè)字節(jié)拆成2個(gè)字節(jié)來用,然而這一次實(shí)在沒辦法沒改接收數(shù)據(jù)類型,然后把一個(gè)double類型拆成了4個(gè)uint16來使用,沒想到出問題了。
所以這里簡單的模擬演示了一下:
A工用一個(gè)double類型取地址,然后把地址強(qiáng)制轉(zhuǎn)為uint64_t類型,以此類型指針取內(nèi)容,當(dāng)這段代碼執(zhí)行完程序就跳到了異常中斷,導(dǎo)致死機(jī)。
其實(shí)這段代碼對(duì)于經(jīng)驗(yàn)豐富的人來說,一看就覺得很變扭,但是無論如何也不至于死機(jī)呀,畢竟強(qiáng)制類型轉(zhuǎn)化大部分人拿來都是隨便用。
3bug解讀
當(dāng)看到A工寫的這一套代碼,bug菌其實(shí)隱隱約約就感覺這塊有些問題,但是沒敢確定,畢竟整套代碼也是前人留下的,全是邏輯沒什么精華也沒有過細(xì)研究,最后看這段代碼的匯編才知道問題所在。
在之前bug菌也曾比較詳細(xì)的出過一篇分析此類問題的文章,可能這一塊并沒有吸引到你,不過還是一句話:"出來混都是要還的!"。
其實(shí)問題就出在LDRD這個(gè)ARM匯編指令上,LDRD指令表示從指定內(nèi)存地址取double word,上面圖片代碼中的LDRD R0,R1,[R2,#0x2EC],可以分解為下面兩個(gè)ldr步驟 :
在ARM匯編指令集中LDRD和STRD是一對(duì)加載和提取指令,一般都需要使用__align(8)修飾來保證數(shù)據(jù)對(duì)象進(jìn)行8直接對(duì)齊,而使用#pragma pack(8)是來指定結(jié)構(gòu)體成員變量相對(duì)于第一個(gè)變量的地址的偏移量的對(duì)齊方式。
__align指示編譯器在 n 字節(jié)邊界上對(duì)齊變量,是一個(gè)存儲(chǔ)類修飾符,當(dāng)然也可以以讓2字節(jié)的對(duì)象進(jìn)行4字節(jié)對(duì)齊其與8字節(jié)對(duì)齊是等價(jià)的,一定要記得是存儲(chǔ)的起始地址為8的整數(shù)倍。
對(duì)齊可以在一定程度上提高數(shù)據(jù)提取的效率,一旦起始地址沒有對(duì)齊會(huì)導(dǎo)致對(duì)齊錯(cuò)誤,所以上面的double浮點(diǎn)類型的結(jié)構(gòu)體變量沒有8字節(jié)地址對(duì)齊,當(dāng)進(jìn)行強(qiáng)制類型轉(zhuǎn)化并使用LDRD指令就導(dǎo)致未對(duì)齊故障。
3更專業(yè)點(diǎn)
當(dāng)然對(duì)于跳轉(zhuǎn)到硬件異常的故障是非常好排查的,下面這篇文章教你如何迅速的定位故障位置和故障信息 :
對(duì)于非對(duì)齊指令的執(zhí)行會(huì)導(dǎo)致指令用法上的故障,那么Cortex芯片中相應(yīng)的故障寄存器標(biāo)志位會(huì)置位。
以上來自于Cortex技術(shù)文檔,文檔中也寫得非常的詳細(xì)。
當(dāng)CPU嘗試做一個(gè)未對(duì)齊的內(nèi)存訪問,然后就會(huì)發(fā)生此錯(cuò)誤。特別是對(duì)于未對(duì)齊的LDM/STM/LDRD/STRD指令,所以進(jìn)入異常中斷以后查詢芯片內(nèi)部故障寄存器也是可以找到問題所在的,對(duì)于使用仿真器排查是再簡單不過了,如果是離線排查就需要進(jìn)行上篇文章那樣打印相關(guān)日志來定位問題。
本文來源:公眾號(hào):最后一個(gè)bug
審核編輯:湯梓紅
-
STM32
+關(guān)注
關(guān)注
2290文章
11018瀏覽量
362912 -
代碼
+關(guān)注
關(guān)注
30文章
4891瀏覽量
70344 -
BUG
+關(guān)注
關(guān)注
0文章
156瀏覽量
15975
原文標(biāo)題:stm32一個(gè)強(qiáng)制類型轉(zhuǎn)換死機(jī),讓我付出了慘痛的代價(jià)~
文章出處:【微信號(hào):嵌入式情報(bào)局,微信公眾號(hào):嵌入式情報(bào)局】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
TCP中強(qiáng)制類型轉(zhuǎn)換
laview中強(qiáng)制類型轉(zhuǎn)換控件使用的一些心得
強(qiáng)制類型轉(zhuǎn)換問題
一個(gè)奇怪的現(xiàn)象,增加結(jié)構(gòu)節(jié)點(diǎn)后,影響強(qiáng)制類型轉(zhuǎn)換的速度
請(qǐng)問使用強(qiáng)制數(shù)據(jù)類型轉(zhuǎn)換函數(shù)的時(shí)候,數(shù)據(jù)類型type端該如何設(shè)置,才能使數(shù)據(jù)成功轉(zhuǎn)換類型?
這算是一個(gè)STM32的BUG嗎?
基礎(chǔ):stateflow中變量的強(qiáng)制類型轉(zhuǎn)換
清除labview的強(qiáng)制類型轉(zhuǎn)換的緩存
iOS 10-iOS 10.2.1驚現(xiàn)大BUG!按下這兩個(gè)鍵立刻死機(jī)
蘋果iOS10.2出現(xiàn)死機(jī)Bug,只需按下兩個(gè)鍵,輕松解決
強(qiáng)制類型轉(zhuǎn)換是把變量從一種類型轉(zhuǎn)換為另一種數(shù)據(jù)類型
C++之類型轉(zhuǎn)換函數(shù)詳解
STM32復(fù)位死機(jī)(無法啟動(dòng))

C語言如何掌握強(qiáng)制類型轉(zhuǎn)換的精髓

評(píng)論