你好,我是雜湯君。
最近踩了公交車錯誤的坑,簡單總結(jié)了一下,再分享一下。
什么是公交車錯誤?
平時開發(fā)過程中,我們經(jīng)常遇到的導(dǎo)致流程崩潰的錯誤大部分是分段錯誤。段錯誤是指訪問超出系統(tǒng)提供的內(nèi)存空間的內(nèi)存,包括空指針操作、數(shù)組超出范圍等。
與段錯誤一樣,總線錯誤(Bus Error)是因?yàn)閷ξ磁判虻刂返脑L問導(dǎo)致CPU讀數(shù)據(jù)違反了特定的總線規(guī)則。
出于性能考慮,當(dāng)需要訪問數(shù)據(jù)時,CPU必須對地址進(jìn)行排序。如果不是地址排序訪問,SIGBUS信號將發(fā)送到進(jìn)程,進(jìn)程將生成核心dump。
總線錯誤與CPU體系結(jié)構(gòu)相關(guān),某些體系結(jié)構(gòu)中的CPU支持支持無序訪問。下面我們通過例子分析一下。
總線錯誤示例
# include
# include
#pragma pack(1)
Struct struct_x
{
CHAR A;
float b;
CHAR C;
}
#pragma pack()
int main(void)
{
struct struct _ x test={ 0 };
printf(' sizeof(struct struct _ x)=% LD \ n ',size of(測試));
=1;
=2.0;
=3;
char * a=;
float * b=;
char * c=;
Printf('*a=%d,addr=%p\n ',*a,a);
Printf('*b=%f,addr=%p\n ',*b,b);
Printf('*c=%d,addr=%p\n ',*c,c);
return 0;
}#pragma pack編譯器排序可以更改。
#pragma pack(n) /*指定以n字節(jié)對齊*/
#pragma pack() /*取消對齊自定義字節(jié)*/在PC端正常工作。
X86/x64系列CPU都支持非對齊訪問,因此還提供了禁用此機(jī)制的開關(guān)。如果X86/x64體系結(jié)構(gòu)不需要排序訪問,則會產(chǎn)生性能成本。
但是,在arm主板上測試以下內(nèi)容:
發(fā)生總線錯誤,因?yàn)楹诵淖兞縯est的成員B的地址是未排序的地址。CPU訪問地址要求是4字節(jié)對齊,訪問*(addr0x001)導(dǎo)致異常。
此時,請?jiān)趕truct_x的成員a、b之前添加占3個字節(jié)的成員d,以查看是否報告了錯誤。
Struct struct_x
{
CHAR A;
茶d[3];
float b;
CHAR C;
}
此時,成員b可以正常訪問,因?yàn)閎的地址在4字節(jié)對齊地址中。
上述公交車錯誤無疑是由于對齊問題造成的。
但是這里有一個疑問。將成員B的類型更改為int類型是否會導(dǎo)致總線錯誤?
# include
# include
#pragma pack(1)
Struct struct_x
{
CHAR A;
int b;
CHAR C;
}
#pragma pack()
int main(void)
{
struct struct _ x test={ 0 };
printf(' sizeof(struct struct _ x)=% LD \ n ',size of(測試));
=1;
=2;
=3;
char * a=;
int * b=;
char * c=;
Printf ('sizeof (float)=% d,sizeof (int)=% d \ n ',sizeof (float),sizeof (int)
Printf('*a=%d,addr=%p\n ',*a,a);
Printf('*b=%d,addr=%p\n ',*b,b);
Printf('*c=%d,addr=%p\n ',*c,c);
return 0;
}
其中,int類型的b成員可以正常訪問。其中,成員B的地址與上面發(fā)生總線錯誤的成員B的地址(float類型)完全相同。float類型和int類型也占用4個字節(jié),但int類型B成員可能支持未排序的訪問。
現(xiàn)在,暫時認(rèn)為CPU是這樣設(shè)計(jì)的。能說明這個問題的朋友歡迎評論討論。感謝大家。
摘要
上述int類型的B成員可以正常訪問,但在實(shí)際編程中,必須小心修改排序。如有必要,請嘗試使修改后的排序的代碼范圍盡可能小。例如,只關(guān)注結(jié)構(gòu)體,很清楚有這樣的事情,所以在后面添加代碼時要非常小心。
以上是這次分享。如果你認(rèn)為文章有幫助,請轉(zhuǎn)達(dá),謝謝。(大衛(wèi)亞設(shè))。
我想你喜歡:
共享好的嵌入式數(shù)據(jù)摘要貼紙。
1024G嵌入式資源廣播!包括但不限于C/C、單片機(jī)、Linux等。私信回復(fù)1024,可以免費(fèi)收到!
1.《【海爾總線數(shù)據(jù)調(diào)亂了怎么辦】通過例子了解公交車錯誤,不要踩坑?!吩曰ヂ?lián)網(wǎng),旨在傳遞更多網(wǎng)絡(luò)信息知識,僅代表作者本人觀點(diǎn),與本網(wǎng)站無關(guān),侵刪請聯(lián)系頁腳下方聯(lián)系方式。
2.《【海爾總線數(shù)據(jù)調(diào)亂了怎么辦】通過例子了解公交車錯誤,不要踩坑?!穬H供讀者參考,本網(wǎng)站未對該內(nèi)容進(jìn)行證實(shí),對其原創(chuàng)性、真實(shí)性、完整性、及時性不作任何保證。
3.文章轉(zhuǎn)載時請保留本站內(nèi)容來源地址,http://f99ss.com/why/3089348.html