1情景
售后 : X工,現(xiàn)場(chǎng)出大事了,今天升級(jí)的程序跑著跑著就掛了!現(xiàn)在整個(gè)產(chǎn)線都等著這個(gè)設(shè)備恢復(fù),能安排個(gè)人過(guò)來(lái)支援下嗎?
bug菌 : my god !別慌,我問(wèn)一下負(fù)責(zé)的A工。
bug菌 : 喂,A工,昨天升級(jí)的程序有問(wèn)題,程序卡死,售后在現(xiàn)場(chǎng)你聯(lián)系一下,支援他一波,順便把程序發(fā)送給我一份,一起看看!
A工 : 啊,還有這種事,程序沒(méi)改什么呀,行,我跟售后聯(lián)系一下。
經(jīng)過(guò)一番折騰,發(fā)現(xiàn)由于程序測(cè)試不到位,導(dǎo)致了一個(gè)強(qiáng)制類型轉(zhuǎn)化引發(fā)的進(jìn)入異常,這里就分享給大家。
2bug演示
這是一個(gè)老項(xiàng)目,采用stm32F4芯片為主控,由于硬件限制而客戶又不愿意花大價(jià)錢改造,所以程序架構(gòu)等等都沒(méi)有再大動(dòng)作,由于通信上的傳輸和解析都是字節(jié)流,一些小的需求都只是在原來(lái)的通信架構(gòu)上把4個(gè)字節(jié)拆成2個(gè)字節(jié)來(lái)用,然而這一次實(shí)在沒(méi)辦法沒(méi)改接收數(shù)據(jù)類型,然后把一個(gè)double類型拆成了4個(gè)uint16來(lái)使用,沒(méi)想到出問(wèn)題了。
所以這里簡(jiǎn)單的模擬演示了一下:
A工用一個(gè)double類型取地址,然后把地址強(qiáng)制轉(zhuǎn)為uint64_t類型,以此類型指針取內(nèi)容,當(dāng)這段代碼執(zhí)行完程序就跳到了異常中斷,導(dǎo)致死機(jī)。
其實(shí)這段代碼對(duì)于經(jīng)驗(yàn)豐富的人來(lái)說(shuō),一看就覺(jué)得很變扭,但是無(wú)論如何也不至于死機(jī)呀,畢竟強(qiáng)制類型轉(zhuǎn)化大部分人拿來(lái)都是隨便用。
3bug解讀
當(dāng)看到A工寫的這一套代碼,bug菌其實(shí)隱隱約約就感覺(jué)這塊有些問(wèn)題,但是沒(méi)敢確定,畢竟整套代碼也是前人留下的,全是邏輯沒(méi)什么精華也沒(méi)有過(guò)細(xì)研究,最后看這段代碼的匯編才知道問(wèn)題所在。
在之前bug菌也曾比較詳細(xì)的出過(guò)一篇分析此類問(wèn)題的文章,可能這一塊并沒(méi)有吸引到你,不過(guò)還是一句話:"出來(lái)混都是要還的!"。
其實(shí)問(wèn)題就出在LDRD這個(gè)ARM匯編指令上,LDRD指令表示從指定內(nèi)存地址取double word,上面圖片代碼中的LDRD R0,R1,[R2,#0x2EC],可以分解為下面兩個(gè)ldr步驟 :
在ARM匯編指令集中LDRD和STRD是一對(duì)加載和提取指令,一般都需要使用__align(8)修飾來(lái)保證數(shù)據(jù)對(duì)象進(jìn)行8直接對(duì)齊,而使用#pragma pack(8)是來(lái)指定結(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ù)提取的效率,一旦起始地址沒(méi)有對(duì)齊會(huì)導(dǎo)致對(duì)齊錯(cuò)誤,所以上面的double浮點(diǎn)類型的結(jié)構(gòu)體變量沒(méi)有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ì)置位。
以上來(lái)自于Cortex技術(shù)文檔,文檔中也寫得非常的詳細(xì)。
當(dāng)CPU嘗試做一個(gè)未對(duì)齊的內(nèi)存訪問(wèn),然后就會(huì)發(fā)生此錯(cuò)誤。特別是對(duì)于未對(duì)齊的LDM/STM/LDRD/STRD指令,所以進(jìn)入異常中斷以后查詢芯片內(nèi)部故障寄存器也是可以找到問(wèn)題所在的,對(duì)于使用仿真器排查是再簡(jiǎn)單不過(guò)了,如果是離線排查就需要進(jìn)行上篇文章那樣打印相關(guān)日志來(lái)定位問(wèn)題。
本文來(lái)源:公眾號(hào):最后一個(gè)bug
審核編輯:湯梓紅
-
STM32
+關(guān)注
關(guān)注
2258文章
10828瀏覽量
352530 -
代碼
+關(guān)注
關(guān)注
30文章
4672瀏覽量
67779 -
BUG
+關(guān)注
關(guān)注
0文章
155瀏覽量
15628
原文標(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)先 登錄
相關(guān)推薦
評(píng)論