結構體成員非對齊訪問所帶來的思考

結構體成員非對齊訪問所帶來的思考

Sailor_forever  sailing_9806#163.com


(本原創文章發表於Sailor_forever 的個人blog,未經本人許可,不得用於商業用途。任何個人、媒體、其他網站不得私自抄襲;網絡媒體轉載請註明出處,增加原文鏈接,否則屬於侵權行爲。如有任何問題,請留言或者發郵件給sailing_9806#163.com)
http://blog.csdn.net/sailor_8318/archive/2010/01/12/5178990.aspx


【摘要】本文介紹了內存訪問時爲什麼需要對齊及不對齊時帶來的影響。接着介紹瞭如何改變對齊規則來保證CPU能夠訪問非對齊內存。最後介紹了結構體設計時需要注意的問題,如何調整成員順序或者填充特定單元來避免平臺差異所帶來的潛在異常。

【關鍵字】X86 MIPS PowerPC alignment exception 非對齊訪問 存儲器週期

 

 

1    問題的引子
在論壇上看到的一個帖子,如下:
//////////////////////////////
標  題: 交叉編譯器導致sizeof結果不一致  
剛剛解決了一個問題
一個程序莫名其妙地就運行不了了
仔細檢查之後發現原來是一個宏裏面包含sizeof(某數據結構)
 
在4.2版本的arm-linux-gcc 下這個sizeof的結果是16
在3.4.3版本下結果是24
 
略有無語。。。開始怎麼也沒想到是這個問題,以爲是代碼版本控制或者硬件出了問題
/////////////////////////////////

首先明確一點,基於不同CPU甚至是相同的CPU但不同的編譯器版本
對結構體的對齊都可能不一樣,這就將導致結構體大小的差異

2    結構體爲什麼需要對齊?


一是因爲跨CPU通信 需要保證雙方對數據的解析一致 這就要求有相同的對齊規則
二是因爲 非對齊的數據 需要多個存儲器訪問週期才能取得所需要的數據 造成效率低下 當然這個低下 你從C語言級別是看不出來的 彙編指令級也看不出來 只能從存儲器的總線時序上看
所以編譯器一般會自動對齊  以空間換時間
三是因爲 有些CPU不支持非對齊訪問 爲什麼不支持 因爲效率低 乾脆直接當異常處理得了
據我所知X86在硬件級別支持非對齊訪問 也就是說不對齊的問題 軟件無法感知
但MIPS 龍芯 Sparc PPC ARM等就不支持非對齊訪問 這時候會拋出一個異常
有些操作系統如Linux會自動對異常進行糾正 保證得到正確的值
對程序員來說 你不會覺得有任何問題  但是對於OS來說 那可是費了九牛二虎之力啊

3    如何改變結構體的對齊規則?


可以人爲的改變對齊規則 但是不同的方法 控制的粒度是不一樣的
makefile可以控制整個工程的對齊規則
pragma pack(n)和pragma pack(n)配合可以控制此區間的對齊規則
__attribute((packed (n))可以控制特定的結構體的對齊規則
可見影響一個結構體大小的因素太多了

是不是結構體對齊了就能保證程序沒有問題呢 顯然不是
是否對齊只是改變了數據的存儲方式 並不能改變CPU訪問數據的方式
對於不支持非對齊訪問的CPU 在半字地址訪問字仍然會造成異常
雖說OS能夠處理這個異常 但是代價太大了 
這樣倒不如直接告訴編譯器 默認以非對齊的方式來訪問數據
這正式__attribute((packed (n))的功能 也是區別於其他改變對齊規則的機制
這個時候會編譯成多條指令來訪問__attribute((packed (n))修飾的數據
相對於OS異常處理來說代價小了 但相對於對齊訪問來說 還是有代價
想想如果通篇都是這樣的數據  一個字都得分成4個字節來訪問 那效率是指數下降的

4    如何保證自動對齊?如何避免訪存失敗?如何提高訪存效率?


那麼我們怎麼樣才能保證我們定義的結構體不隨着平臺及編譯器的版本而變化呢
合理調整成員的順序及人爲的進行填充  保證已經對齊了
這樣不論什麼編譯器 結構體的大小都是固定的
因爲是對齊的數據  無論CPU是否支持非對齊訪問 都不會產生異常
因爲是對齊訪問 所以不會損失效率
唯一的代價就是浪費了一定人爲填充的空間
但這一點空間效率的損失帶來的效益卻是無窮的
不光程序運行的效率提高了  程序跨平臺的可移植性也強了  在任意的CPU上都有一致的表現

其實除了結構體會帶來非對齊訪問的問題,指針的強制轉換也是一個潛在的不對齊的問題。因此應該避免強制進行指針轉換,而是讓編譯器以warning的形式告訴我們,這樣可以確認這個強制轉換是否有問題。

Windows程序員永遠不需要爲內存對齊問題操心費神
但他們太安樂了 可惜的是也享受不到異常帶來的刺激
這也正是嵌入式程序員的幸福所在  因爲有問題 所以我們纔會懂的更多
痛  但我們快樂着

一個很有趣的帖子,問題雖小,但卻折射了很多問題,直接看到凌晨三點多,還是很帶勁
http://topic.csdn.net/t/20030707/17/2000453.html#

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章