在《C專家編程》中提到了匯流排錯誤bus error(core dumped)。
匯流排錯誤幾乎都是由於未對齊的讀或寫引起的。
它之所以稱為匯流排錯誤,是因為出現未對齊的記憶體訪問請求時,被堵塞的組件就是地址匯流排。對齊的意思就是資料項目只能儲存在地址是資料項目大小的整倍數的記憶體位置上。
現代的電腦架構中,尤其是RISC架構,都需要字對齊,因為與任意的對齊有關的額外邏輯都會使記憶體系統更大且更慢。
通過迫使每個記憶體訪問局限在一個cache行或者一個單獨的頁面內,可以極大地簡化(並加速)如cache控制器和記憶體管理單元這樣的硬體。
頁和cache的大小都是經過精心設計的,這樣只要遵守對齊規則就可以保證一個原子資料項目不會跨過一個頁或cache塊的邊界。
書中還給出了匯流排錯誤的例子:
union { char a[10]; int i;}u;int *p =(int*)&(u.a[1]);*p =17;/*p中未對齊的地址將會引起匯流排錯誤,因為數組和int的聯合確保了a是按照int的4位元組來對齊的,所以“a+1”肯定不是int來對齊的。*/
但是在實際的運行中並沒有出現該錯誤,我的環境是CentOS release 6.2,2.6.32-279.14.1.el6.i686,gcc 4.4.6
後來在網上參考了一個sample程式,將程式修改為如下:
#include <stdlib.h>int main(int argc, char **argv) {#if defined(__GNUC__)# if defined(__i386__) /* Enable Alignment Checking on x86 */ __asm__("pushf\norl $0x40000,(%esp)\npopf");# elif defined(__x86_64__) /* Enable Alignment Checking on x86_64 */ __asm__("pushf\norl $0x40000,(%rsp)\npopf");# endif#endif union{ char a[10]; int i; }u; int *p =(int*)&(u.a[1]); *p =17;}
運行結果如下:
Bus error (core dumped)
原因是:
x86體繫結構會把地址對齊之後,訪問兩次,然後把第一次的尾巴和第二次的頭拼起來。
如果不是x86,那種體繫結構下的機器不肯自動幹這活,就會產生core。
如果在代碼中將對齊檢查功能開啟,運行後能顯示bus error