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