2014-10-02 67 views
2

我有一個動態定義的無符號的8位整數的數組:GCC浮子指針鑄造在C++中引起錯誤SIGBUS

const uint8_t *data; 

這包含一個字節流,並且被重新解釋爲各種數據類型。我可以在這個數據流重新詮釋的位置ň作爲基本型類型

type value = *((type*) &data[n]); 

此使用gcc Linux下編譯時使用Visual Studio編譯器的Windows下的所有數據類型工作正常,但是,當類型是一個浮點數(解引用的位置在數據數組範圍內)時,會產生一個SIGBUS錯誤。進一步的調查顯示,它是導致此錯誤的指針解除引用。我已經通過使用memcpy解決了這個問題,但想知道爲什麼這會導致問題,首先看到引用的地址是有效的。 reinterpret_cast會更合適嗎?如果是這樣,爲什麼?

編輯:

我沒有提到,Linux系統有ARM架構。 @MSalters指出,差異配置可能會有更嚴格的指針對齊要求。一個簡短的研究表明,雖然上述內容在x86體系結構上有效(儘管C/C++標準不允許),但ARM上未對齊的指針解引用將導致總線錯誤。

+0

如果你這樣做是在暗中搗鬼,我會考慮再來看看設計 – 2014-10-02 10:05:19

+0

它只能和花車發生的呢?或者其他類型與float相同? – James 2014-10-02 10:08:19

+0

該設計適用於允許通過rs232接口進行通信的網絡協議,以及位於tcp/ip之上的網絡協議。數據類型是在幀頭中定義的,所以需要這種解釋。 – Hampycalc 2014-10-02 10:09:12

回答

5

演員確實是這個問題。它已經是reinterpret_cast,即使你使用了舊的C語法。但只有當&data[n]實際上是有效的float*時才允許投射。 SIGBUS表示它不是。該地址可能是有效的char*地址,但這並不意味着它是有效的float*地址。特別是,float*可能有更嚴格的對齊要求。

+0

是的,謝謝。我沒有提到Linux系統是基於ARM的,而Windows系統是x86/x86_64。我之前沒有對齊要求的問題,但我的經驗僅限於x86 CPU架構。我將堅持使用memcpy來保證我的代碼完全可移植。 – Hampycalc 2014-10-02 10:20:17

+0

好吧,x86對於對齊錯誤也不滿意,但是懲罰是放緩的。 – MSalters 2014-10-02 10:21:40

+0

這值得一提! ARM對齊非常挑剔,你會在x86上遇到謀殺。 – Joe 2014-10-02 10:27:43

1

由於MSalters在此線程中提到,轉換的目標類型的對齊要求比源類型的對齊要求更強,這會導致不處理未對齊訪問的CPU上的SIGBUS

處理這件事的方法是memcpy

const uint8_t *data = ...; 
type value; 
memcpy(&value, data, sizeof value);