本文轉(zhuǎn)自公眾號(hào)歡迎關(guān)注
https://mp.weixin.qq.com/s/ErIa2ss2YZLGYbSwoJEzog
一.前言
內(nèi)存未對(duì)齊訪問(wèn)問(wèn)題這個(gè)已經(jīng)是老生常談的問(wèn)題了, 由于LWIP的堆管理中也用到了地址(指針)強(qiáng)制轉(zhuǎn)換所以也會(huì)遇到這個(gè)問(wèn)題。對(duì)于老手比較容易發(fā)現(xiàn),對(duì)于新手可能會(huì)比較疑惑。所以也單獨(dú)分享一個(gè)案例吧,權(quán)當(dāng)一個(gè)小的check list的case。
二.問(wèn)題
Lwipopts.h中MEM_ALIGNMENT可以配置堆對(duì)齊大小,有問(wèn)題時(shí)是配置為1
#define MEM_ALIGNMENT 1U
異常時(shí)打印寄存器如下,當(dāng)然不同平臺(tái)異常時(shí)如何獲取上下文信息方式不一樣,不在本文討論范圍內(nèi),我這里是RISC-V環(huán)境。
看到打印的mepc是0x20006C88,異常原因是地址未對(duì)齊。
所以是在運(yùn)行0x20006C88時(shí)進(jìn)入了異常,當(dāng)然這個(gè)地方不一定是原始問(wèn)題所在點(diǎn),異??赡苁桥芰撕芫貌懦霈F(xiàn)的。
所以先在這里打個(gè)斷點(diǎn)試試
可以看到是pbuf.c的代碼中,所以可以懷疑是內(nèi)存池或者堆的問(wèn)題。
我們運(yùn)行發(fā)現(xiàn)斷點(diǎn)并不能觸發(fā),之前就已經(jīng)異常了,所以只能跟代碼逐漸縮小范圍確認(rèn)問(wèn)題的。一般采用的方式是,逐步斷點(diǎn)或者打印或者刪除代碼,逐步縮小范圍的方法。
可以借鑒一些二分的思想,加快定位。
這里還是從pbuf開始,先找到相關(guān)代碼上層函數(shù)處,斷點(diǎn)
b pbuf_init_alloced_pbuf
看到異常前是可以停下來(lái)的
看到此時(shí)p的值是0x28201406
查看如下匯編代碼可知
sw zero,0(a0)即對(duì)應(yīng)代碼p->next = NULL;
sw是word操作指令,但是地址a0不是word對(duì)齊,所以會(huì)產(chǎn)生異常
再si單步確實(shí)進(jìn)入異常
所以問(wèn)題確認(rèn)了。
因?yàn)槎咽欠峙涞囊粔K區(qū)域,每一塊區(qū)域的開始地址對(duì)齊值就是上面設(shè)置的對(duì)齊大小,分配區(qū)塊后作為其他模塊使用,比如pbuf使用,前面部分作為管理結(jié)構(gòu)體
struct pbuf 操作,所以實(shí)際是將一個(gè)區(qū)塊地址強(qiáng)制轉(zhuǎn)為了結(jié)構(gòu)體指針。
此時(shí)訪問(wèn)結(jié)構(gòu)體成員,編譯器是自動(dòng)按照自然對(duì)齊生成匯編指令的,因?yàn)榫幾g器并不知道你的對(duì)齊要求,所以如果系統(tǒng)不支持對(duì)應(yīng)的指令非對(duì)其訪問(wèn)就有問(wèn)題,但是有些系統(tǒng)對(duì)應(yīng)的匯編指令的行為支持不對(duì)齊訪問(wèn)那么就沒(méi)有問(wèn)題。
當(dāng)然出于可靠性設(shè)計(jì),建議不要進(jìn)行強(qiáng)制類型轉(zhuǎn)換,比如MISRA標(biāo)準(zhǔn)里的規(guī)范就是如此。
如果代碼要做到兼容性可靠性非常好就要注意這個(gè)問(wèn)題,此時(shí)不能使用強(qiáng)制類型轉(zhuǎn)換,而是使用字節(jié)序手動(dòng)拼接得到成員的值。
但是出于靈活性考慮,很多協(xié)議棧的設(shè)計(jì)都是直接使用強(qiáng)制類型轉(zhuǎn)換的,所以這時(shí)用戶就需要注意,比如這里我們可以配置#define MEM_ALIGNMENT 4U
來(lái)保證上述分配出來(lái)的地址p是4字節(jié)對(duì)齊的,所以按照偏移,其成員也是4字節(jié)對(duì)齊的,sw指令操作的就是4字節(jié)對(duì)齊的成員,就不會(huì)有問(wèn)題。
三.總結(jié)
以上分享一個(gè)簡(jiǎn)單的案例,目的是提醒下要注意類似問(wèn)題,尤其有指針強(qiáng)制類型轉(zhuǎn)換的要注意對(duì)齊問(wèn)題。問(wèn)題不難,也不復(fù)雜,但是可以作為check list的case可以作為檢查項(xiàng)目。
審核編輯 黃宇
-
以太網(wǎng)
+關(guān)注
關(guān)注
40文章
5424瀏覽量
171701 -
LwIP
+關(guān)注
關(guān)注
2文章
86瀏覽量
27168 -
驅(qū)動(dòng)開發(fā)
+關(guān)注
關(guān)注
0文章
130瀏覽量
12077
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論