#pragma pack(1)
struct Base
{
int a;
char b;
int c;
};
template<typename T>
struct Child_X : public Base
{
T data[1];
};
#pragma pack()
猜一下下面兩個sizeof的結果:
sizeof(Base)
sizeof(Child_X<int>)
sizeof(Base) = 9。一些猜對或者沒猜對的同學應該用google好好補充一下基礎知識。
sizeof(Child_X<int>) = sizeof(Base) + sizeof(int) = 13。
應該是13,但是16也是對的,這就是編譯器的差異。
M$的VS2008,執(zhí)行的結果是 sizeof(Child_X<int>) = 13。
linux的gcc-4.4,執(zhí)行結果是 sizeof(Child_X<int>) = 16。
當兩個平臺編譯的程序互相通訊,消息里面包含Child_X<>結構時,肯定會發(fā)生一些不那么有趣的事情。
這個不有趣的事情大概有兩種表現形式:
1.當你明顯的執(zhí)行一個操作后,收到一條不太對頭的Child_X消息,程序崩潰了。這種的問題很容易查。
2.當你執(zhí)行或者不執(zhí)行操作,不久程序崩潰了,根據崩潰看起來是某處內存寫串了,而你在這段時間內沒有收到任何Child_X消息。
不幸的是我遇上的就是第二種情況,這種情況麻煩的地方就在于崩潰的位置和崩潰的原因之間有一段不會太短的距離,其本質就是大小不正確的Child_X消息初始化程序,結果程序的狀態(tài)是不正確的,但是這個不正確的狀態(tài)直到不久使用某些操作才引起嚴重錯誤,而錯誤看起來就像是內存寫串了。
造成這種差異的原因是,VC在實例化模板的時候,使用了定義模板的上下文;而gcc在實例化模板的時候,則使用的是第一次實例化模板的那段代碼的上下文。
我想標準肯定沒有規(guī)定這個細節(jié),不過VC的實現方案更符合常規(guī)的心里預期。而標準委員會除了開會吵架,已經很久沒有作為了。
最后跨平臺的解決方案是,在pack上下文里對模板進行實例化
#pragma pack(1)
template<typename T>
struct Child_X : public Base
{
T data[1];
};
template struct Child_X<short>;
template struct Child_X<int>;
// 不過這種方案只能用來對付需要實例化的類型數量較少的情況
#pragma pack()
posted on 2010-01-09 20:20
LOGOS 閱讀(1752)
評論(3) 編輯 收藏 引用