2009-09-30 41 views
7

根據維基百科頁面Segmentation fault,總線錯誤可能由未對齊的內存訪問引起。本文舉例說明如何觸發總線錯誤。在這個例子中,我們必須啓用對齊檢查來查看總線錯誤。如果我們禁用這種對齊檢查會怎樣?未對齊的內存訪問總是會導致總線錯誤?

該程序似乎正常工作。我有一個程序頻繁地訪問未對齊的內存,並且它被很多人使用,但沒有人向我報告總線錯誤或其他奇怪的結果。如果我們禁用對齊檢查,未對齊內存的副作用是什麼?

平臺:我在x86/x86-64上工作。我也通過在Mac上編譯「gcc -arch ppc」來試用我的程序,並且它正常工作。

+0

什麼是平臺,您正在使用? – 2009-09-30 08:51:30

+0

Pavel Minaev很大程度上回答了我的問題。我正在x86/x86_64上工作。我在Mac上通過編譯「gcc -arch ppc」來試用我的程序,它可以正常工作。 – user172818 2009-09-30 09:01:53

+0

請注意,根據C標準,未對齊的內存訪問(實際上,即使只是指針賦值)也是未定義的行爲 - 因此如果您這樣做(即使並非所有編譯器都會採用這種自由度),兼容的編譯器可以執行任何操作。 – sleske 2015-01-28 23:04:51

回答

8
  1. 訪問未對齊的內存可能會明顯較慢(如在幾倍的速度下)。

  2. 並非所有的平臺甚至支持未對齊的訪問 - x86和x64都支持,但ia64(Itanium)不支持。

  3. 甲編譯器可以仿真對齊訪問(VC++那樣,對於聲明爲__unaligned在IA64指針,例如) - 通過插入額外的檢查,以檢測不對齊的情況下,和裝載/存儲所述對象的部分即跨越對齊邊界分開。然而,這比在本地支持它的平臺上的未對齊訪問慢。

+0

謝謝。我的程序很少有用戶在使用ia64。也許這就是爲什麼我沒有收到錯誤報告。 – user172818 2009-09-30 09:04:26

+6

您還可以添加#4,OS可以通過捕獲處理器異常並修復它(類似於頁面錯誤發生的情況)來模擬應用程序的未對齊訪問。這比編譯器在生成的代碼中執行未對齊的修正更慢。 Windows可以在ia64中支持這個功能。 – 2009-09-30 14:03:13

+6

此答案已在博客文章中引用* [數據對齊速度:神話還是現實?](http://lemire.me/blog/archives/2012/05/31/data-alignment-for-speed-myth-或現實/)*。 – 2012-06-07 16:24:00

6

它非常依賴芯片架構。 x86和POWER非常寬容,Sparc,Itanium和VAX拋出了不同的例外。

+0

非常感謝你的答案。 – user172818 2009-09-30 09:07:48

+7

它確實取決於處理器,最近我開發了一個DSP,當被要求在一個未對齊的存儲器地址上進行操作時,它將使用最接近的對齊的存儲器地址來開展工作。 *,你錯誤地訪問個人的未對齊的內存。 – 2009-09-30 12:18:52

+0

事實上,爲什麼還要仔細查看最後幾位 - 真正的男人知道他們在做什麼,反正:)另一方面,如果使用被忽略的位,那麼使用標記指針將是一個方便的體系結構爲標籤... – 2009-09-30 16:23:41

2

請看下面的例子中,我剛纔在ARM9測試:

//Addresses  0  1  2 3  4  5  6  7  8 9 
U8 u8Temp[10] = {0x11,0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00}; 

U32 u32Var; 

u32Var = *((U32*)(u16Temp+1)); // Let's read four bytes starting from 0x22 

// You would expect that here u32Var will have a value of 0x55443322 (assuming we have little endian) 
// But in reallity u32Var will be 0x11443322! 
// This is because we are accessing address which %4 is not 0. 
+2

我認爲您的拼寫錯誤 - 您的第三條語句引用了「 u16Temp'變量,它的聲明在哪裏?我只看到'u8Temp'。 – amn 2013-06-29 16:06:07