关于内存对齐
?
??? 曾經(jīng)接手一個網(wǎng)絡視頻監(jiān)控程序,主要是上層軟件通過發(fā)送控制指令獲取網(wǎng)絡視頻板的視頻數(shù)據(jù)和控制網(wǎng)絡視頻板,這應該是一個比較簡單的流程!
一切的開發(fā)都很順利,測試的時候,問題就來了,獲取視頻數(shù)據(jù)流的數(shù)據(jù)竟然是錯誤的,我糊涂了,把整個程序流程,用調試器一步一步地跑,到了發(fā)送視頻指令的時候,返回指令操作錯誤的結果,怎么回事?我是按照視頻的操作指令封裝的數(shù)據(jù)包,內存顯示數(shù)據(jù)包的內容是沒有錯誤的,就是一個晚上,我不停地找"錯誤",只有偶然,我把sizeof()這個指令直接換掉,把數(shù)據(jù)包全部用一個BYTE的數(shù)據(jù)進行copy,程序成功執(zhí)行!這時,我已經(jīng)快暈了!
數(shù)據(jù)發(fā)送到網(wǎng)絡板的數(shù)據(jù)包大小根本不是實際控制數(shù)據(jù)包的大小!
這時我才想起一個人, Stanley B. Lippman,他寫的那一本書 "Inside object modale", 曾經(jīng)提過這樣的事情,編譯器為了提高CPU的效率,會對struct 的結構進行優(yōu)化,利用sizeof 可以得出不同的計算機上對 struct 的結構優(yōu)化后的大小值.以前是看過,但是,卻沒有深刻理會,現(xiàn)在,吃了苦頭,才明白!
這是我的理解,C++ 編譯器為了使CPU的性能達到最佳,會對 struct 的內存結構進行優(yōu)化,這是為了達到CPU數(shù)據(jù)傳輸總線的吞吐值,各個計算機的數(shù)據(jù)傳輸總線是不一樣的,如32位的計算機的數(shù)據(jù)傳輸值是4 bytes,64位計算機數(shù)據(jù)傳輸是8 bytes,這樣,struct 在默認的情況上,編譯器會對 struct 的結構進行數(shù)據(jù)對齊((32位機)4的倍數(shù)或(64位機)8的倍數(shù)),如下面這段代碼所示:
#include typedef struct tagPACKAGE {int intValue;char chValue1;char chValue2; } PACKAGE, * LP_PACKAGE;int main() {PACKAGE package;std::cout << "sizeof( package ) = " << sizeof( package ) << std::endl;return 0; }
程序執(zhí)行結果為 8 ( sizeof( int ) + sizeof( char ) + sizeof( char ) + 對齊值 )為8. (我的機子是32位,4*2=8)一切都是編譯器搞得自已頭暈,但是為什么以前自已寫的網(wǎng)絡程序沒有這種情況?同樣的數(shù)據(jù)包傳輸,我并沒有阻止編譯進行強制對齊,我猜可能是操作系統(tǒng)都是一樣(都是WinX系統(tǒng))的才沒有出現(xiàn)問題,而現(xiàn)在的網(wǎng)絡視頻板是內嵌式linux,對數(shù)據(jù)包的處理是純數(shù)據(jù)(不經(jīng)對齊的數(shù)據(jù))是敏感的所以,才會出現(xiàn)這樣的問題!這種情的解決方法是阻止編譯器對數(shù)據(jù)包對齊,因為數(shù)據(jù)對齊的時候,編譯器會塞入一些沒有意義的數(shù)據(jù)對結構進行對齊,使用#pragma 強制編譯器產生指定數(shù)據(jù)對齊方式,如下代碼所示
#pragma pack(push) #pragma pack(1) typedef struct tagPACKAGE {int intValue;char chValue1;char chValue2; } PACKAGE, * LP_PACKAGE; #pragma pack(pop)typedef struct tagPACKAGE2 {int intValue;char chValue1;char chValue2; } PACKAGE2, * LP_PACKAGE2;int main() {PACKAGE package;PACKAGE2 package2;std::cout << "sizeof( package ) = " << sizeof( package ) << std::endl;std::cout << "sizeof( package2 ) = " << sizeof( package2 ) << std::endl;return 0; }
對指定的數(shù)據(jù)包編譯時進行內存對齊,這樣,也不會讓編譯器對其數(shù)據(jù)進行優(yōu)化!
總結:
C++的編譯器總是在背后做了很多事!網(wǎng)絡數(shù)據(jù)處理或與內嵌式設備打交道的時候,這更應該小心!
轉載于:https://www.cnblogs.com/javaspring/archive/2012/04/13/2656151.html
總結
- 上一篇: native-maven-plugin与
- 下一篇: oracle数据库自动备份