程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 關於內存對齊

關於內存對齊

編輯:關於VC++

曾經接手一個網絡視頻監控程序,主要是上層軟件通過 發送控制指令獲取網絡視頻板的視頻數據和控制網絡 視頻板, 這應該是一個比較簡單的流程!

一切的開發都很順利,測試的時候,問題就來了,獲取視 頻數據流的數據竟然是錯誤的,我糊塗了,把整個程序 流程,用調試器一步一步地跑,到了發送視頻指令的時候,返回 指令操作錯誤的結果,怎麼回事?

我是按照視頻的操作指令封裝的數據包,內存顯示數據 包的內容是沒有錯誤的,就是一個晚上,我不停地找"錯 誤",只有偶然,我把sizeof()這個指令直接換掉,把數據包全 部用一個BYTE的數據進行copy,程序成功執行!這時,我 已經快暈了!

數據發送到網絡板的數據包大小根本不是實際控制數 據包的大小!

這時我才想起一個人, Stanley B. Lippman,他寫的那 一本書 "Inside object modale", 曾經提過這樣的事 情,編譯器為了提高CPU的效率,會對struct 的結構進行優化, 利用sizeof 可以得出不同的計算機上對 struct 的結 構優化後的大小值.以前是看過,但是,卻沒有深刻理會,現在,吃了 苦頭,才明白!

這是我的理解,C++ 編譯器為了使CPU的性能達到最佳, 會對 struct 的內存結構進行優化,這是為了達到CPU 數據傳輸總線的吞吐值,各個計算機的數據傳輸總線是不一樣的, 如32位的計算機的數據傳輸值是4 bytes,64位計算機 數據傳輸是 8 bytes,這樣,struct 在默認的情況上,編譯器會對 struct 的結構進行數據對齊((32位機)4的倍數或(64 位機)8的倍數),如下面這段代碼所示:

#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;
}

程序執行結果為 8 ( sizeof( int ) + sizeof( char ) + sizeof( char ) + 對齊值 )為8. (我的機子是32 位,4*2=8)一切都是編譯器搞得自已頭暈,但是為什麼以前自已寫的網 絡程序沒有這種情況?同樣的數據包傳輸,我並沒有阻 止編譯進行強制對齊,我猜可能是操作系統都是一樣(都是WinX系統)的才 沒有出現問題,而現在的網絡視頻板是內嵌式linux,對 數據包的處理是純數據(不經對齊的數據)是敏感的所以,才會出現這樣 的問題! 這種情的解決方法是阻止編譯器對數據包對齊,因為數 據對齊的時候,編譯器會塞入一些沒有意義的數據對結 構進行對齊,使用 #pragma 強制編譯器產生指定數據對齊方式,如下代碼 所示

#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;
}

對指定的數據包編譯時進行內存對齊,這樣,也不會對 編譯對其數據進行優化!

總結:

C++的編譯器總是在背後做了很多事!網絡數據處理或 與內嵌式設備打交道的時候,這更應該小心!

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved