大家應該都知道計算機中間都有位元組對齊問題。cpu訪問記憶體的時候,如果從特定的位址開始訪問一般可以加快速度,比如在32位機器上,如果乙個32位的整數被放在能被32模除等於0的位址上,只需要訪問一次,而如果不在,可能要訪問兩次。但是這樣就要求一些資料從特定的位址開始,而不是順序排放(中間會有一些空餘的位址),這就是位元組對齊。
而ace cdr的估計也是為了加快速度,從而在cdr編碼上預設也使用了位元組對齊。所以在ace的cdr編譯碼過程中,傳入的引數位址最好是能符合位元組對齊規則,否則可能會編譯碼錯誤。
ace_outputcdr建構函式會呼叫乙個函式mb_align調整傳入的位址引數成為位址對齊位址。但是其的調整函式ace_ptr_align_binary不知處於什麼考慮,不是按照機器的對齊長度而是採用的 ace_cdr::max_alignment(64bit,長度為8bytpes)作為引數位址。那麼ace_outputcdr的內部位址是按照8位元組作為對齊的,但是ace_inputcdr卻沒有將內部位址調整為模除64等於0的位址上,而只是調整為模除32(在32位機器上)等於0的位址。
void
ace_cdr::mb_align (ace_message_block *mb)
使用一段簡單的**可以測試發現這個問題。
char *tmp_buffer = new char [2048];
//使用乙個無法對齊的引數作為ace_inputcdr,ace_outputcdr的引數位址,
char *tmp_data = tmp_buffer +1;
// output_cdr調整了對齊的起始位址為8位元組的預設
ace_outputcdr output_cdr(tmp_data,512);
ace_inputcdr input_cdr(tmp_data,512);
ace_cdr::ulong cdr_long = 123;
bool bret =false;
//bret = output_cdr.write_ulong(cdr_long);
// cdr_long 不等於123,而是乙個錯誤無效資料。
bret = input_cdr.read_ulong(cdr_long);
其實如果編譯碼的buff都採用相同的對齊方式,那麼理論上也不應該出現問題,最多是出現為了對齊而進行填補的空隙,但是這樣能帶來cpu的效率提公升,也是好事。但是由於ace_outputcdr的乙個位址調整。卻可能導致編譯碼的buffer不一致,我不能肯定這到底是乙個錯誤還是作者有他自己的考慮。
這個問題到5.6.1還存在。我已經提交了問題報告。
當然有乙個方法解決這個問題。就是定義巨集ace_cdr_ignore_alignment【注】,只要定義了這個巨集,ace就不會使用位元組對齊處理cdr編碼。使用這個方法的,編碼占用空間會壓縮一些,但效率上可能低一點(其實未必,因為為了位元組對齊還要耗費一些計算時間),
【注】ace不知道為什麼在**中使用兩個不使用位元組對齊的巨集,乙個是在cdr_base.h cdr_base.cpp 檔案中使用的是ace_cdr_ignore_alignment,在cdr_stream.cpp和cdr_stream.**件上使用的巨集ace_lacks_cdr_alignment。
我一般將兩個巨集都定義上。
程式設計中的位元組對齊問題
在沒有 pragma pack巨集的情況下,要遵守下面的三個原則 1 資料成員對齊規則 結構 struct 或聯合 union 的資料成員,第乙個資料成員放在offset為0的地方,以後每個資料成員儲存的起始位置要從該成員大小或者成員的子成員大小 只要該成員有子成員,比如說是陣列,結構體等 的整數倍...
位元組對齊的問題
為了能使cpu對變數進行高效快速的訪問,變數的起始位址應該具有某些特性,即所謂的 對齊 例如對於4位元組的int型別變數,其起始位址應位於4位元組邊界上,即起始位址能夠被4整除。變數的對齊規則如下 32位系統 type alignment char 在位元組邊界上對齊 short 16 bit 在雙...
位元組對齊的問題
位元組對齊的細節和具體編譯器實現相關,表現為具體的彙編翻譯可能會因為編譯器的不同而不同,但一般而言,滿足三個準則 1 結構體變數的首位址能夠被其最寬基本型別成員的大小所整除 2 結構體每個成員相對於結構體首位址的偏移量都是成員大小的整數 倍,如有需要編譯器會在成員之間加上填充位元組 例如上面第二個結...