關於arm下獨立指針訪問結構體成員錯誤的問題


這是csdn裏面的一個討論: linux

http://bbs.csdn.net/topics/300096265 數據結構

在ARM core的平臺(StrongARM, 2410, XScale)上,若是企圖經過一個獨立的指針對某個數
據結構的內部成員域進行定位和訪問時,會遇到下面的問題(注,在IA-32 X86平臺不會出現
這樣的問題)。

定義一個數據結構:
struct __attribute__((packed)) test {
char c; // 1個字節
short s; // 2個字節
long l; // 4個字節
} st;

packed屬性,對應於gcc編譯選項 -fpack-struct;

test的內存佈局在該屬性的制約下是緊湊的,也就意味着第二、3個成員s、l的起始地址將是
奇地址。

若是另行定義一個獨立指針: unsigned long t;
經過「t+偏移字節數」的方式來定位(訪問)結構內成員域,則會在強制類型轉換t指針來賦值
或者讀取相應成員域時,出現下面的問題:
(假定該結構的起始地址爲A0, 則c、s、l的地址各爲A0、A一、A3)

1. 編譯器版本(arm version):GCC 2.95.2 / 3.2 / 3.3.2
t = (unsigned long) &st;
*((short*)(t+1)) = 0x0201;
指望: 0x01賦於A1字節, 0x02賦於A2字節
實際: 0x01賦於A0字節, 0x02賦於A1字節,與指望不吻合

*((long*)(t+3)) = 0x08070605;
指望: 0x05 - 0x08 逐次賦於 A3 - A6 字節
實際: 0x05 - 0x08 逐次賦於 A0 - A3 字節,與指望不吻合

結論: 基於這些GCC版本,若是對奇地址進行強制類型轉換,企圖得到"字、雙字"的數據類型,
則強制轉換後所得到的數據類型,其地址將被自動"優化"爲最近的可被相應對齊模數
(字型數據的對齊模數是2,雙字的是4)整除的低位偶地址!

2. 編譯器版本(arm version):GCC 2.95.3 / 3.0
t = (unsigned long) &st;
*((short*)(t+1)) = 0x0201;
指望: 0x01賦於A1字節, 0x02賦於A2字節
實際: 0x01賦於A1字節, 0x02賦於A2字節,與指望吻合

*((long*)(t+3)) = 0x08070605;
指望: 0x05 - 0x08 逐次賦於 A3 - A6 字節
實際: 0x05 - 0x08 逐次賦於 A0 - A3 字節,與指望不吻合

結論: 基於這些GCC版本,若是對奇地址進行強制類型轉換,企圖得到"雙字"的數據類型,
則強制轉換後所得到的數據類型,其地址將被自動"優化"爲最近的可被相應對齊模數
4整除的低位偶地址!但對字型數據的此類操做,卻不會引發這種指針優化。


附,有資料稱:
某些架構上訪問數據時有對齊的要求,好比只能從4字節邊界上讀取一個4字節的數據類型。
IA-32架構沒有硬性要求對齊,儘管未對齊的訪問下降執行效率。另一些架構,好比MIPS、
SPARC、m68k、ARM(<V3),要求對齊訪問,不然向當前進程分發SIGBUS信號,主要是相對早
期的RISC CPU存在此問題。

那麼有沒有一個辦法(好比gcc的編譯選項,或者一個__attribute__),能制約上述的這種指針優化,
使其不自動發生!從而使實際操做與指望操做相吻合?

進一步地問,爲什麼不一樣版本的arm-linux-gcc所編譯出的執行碼的在這個問題上的表現不同!?
這後面有更深層的理論背景嗎?

================
若是endian是肯定的,我喜歡這樣的形式:((unsigned char*)&s)[0] * 256 + ((unsigned char*)&s)[1] 
=============================
en,這樣把操做分解成基於字節的處理確實是一個變通的辦法,和本人的考慮是一致的;在找不出更好解決方法的狀況下,我認爲能夠有下面3種辦法來回避這樣的問題:
1. 改變數據源的結構佈局,放棄緊湊佈局;
代價:增長並浪費了 padding 字節,且既有應用須要重寫,以配合結構體內存佈局的變化;
2. 改變對結構成員的訪問方式,放棄經過獨立指針來定位/讀寫成員域,而直接採用成員名的方式訪問;
代價:既有應用程序的改動範圍較大;
3. 維持目前的數據源和數據訪問方式,而新增一個過渡層,表現形式能夠是一組宏,或者內聯函數,或
者函數,對結構體內的一切字或雙字型數據的訪問,經過這個過渡邏輯被分拆爲以字節爲基礎的操做,
從而回避指針強制類型轉換時發生優化;這也一樣是nxin的思路!
代價:既有應用程序在訪問結構體成員時的代碼形式發生變化,但我的認爲這種方法對系統總體代碼的
影響是最小的。 架構

相關文章
相關標籤/搜索