warning: dereferencing type-punned pointer will break strict-aliasing rules(轉)

http://blog.csdn.net/wuyao721/article/details/4732182

warning: dereferencing type-punned pointer will break strict-aliasing rules

  在 gcc 2.x 下編譯沒有任何 warning 信息的代碼換到 gcc 3.x 版本下之後出現了類似的 warning 。原因是 gcc 3 引入了 strict aliasing 架構,當編譯時使用了 -fstrict-aliasing 參數(該參數在使用了 -O2 , -O3, -Os 優化參數的情況下默認生效),而源代碼中存在一些違反了 strict-aliasing 規則的地方的話,編譯器就會對這部分代碼提出 warning 。

  gcc 3 manual 對於 -fstrict-aliasing 參數的說明是:Allows the compiler to assume the strictest aliasing rules applicable to the language being compiled.  For C (and C++), this activates optimizations based on the type of expressions.  In particular, an object of one type is assumed never to reside at the same address as an object of a different type, unless the types are almost the same.  For example, an "unsigned int" can alias an "int", but not a "void*" or a "double".  A character type may alias any other type.

  簡而言之, 在該參數激活的情況下,編譯器希望不同類型的對象不會指向同一個地址。比如像這段代碼:

int retLen;
someSetFunc((unsigned long *)&retLen);
printf ("ret len = %d/n" ,retLen);

  由於 someSetFunc 的傳入參數類型定義爲 unsigned long ,所以需要進行這樣的指針類型強制 cast 。但對於 -fstrict-aliasing 優化參數來說,這樣的轉換是有潛在問題的(但實際上可能並不會造成任何問題)。所以如果現有的源代碼存在太多這樣的類型強制轉換的問題的話,對這些代碼進行修改也許會是場噩夢。最簡單的方法是使用 -fno-strict-aliasing 參數來關閉 gcc 的優化選項,代價是放棄了 strict-aliasing 編譯優化可能帶來的可執行代碼的性能提升。當然也可以用 -Wno-strict-aliasing 來屏蔽相關的 warning 信息,但無論這些 warning 信息多麼的無關緊要,總還是“疑似危險”,所以可能的話最好還是把所有的 warning 都消滅掉。

  消滅的方法也不算複雜,正如 gcc manual 所示的那樣,可以是採用 union 的不同成員變量來完成類型的轉換。上面那段代碼可以改爲:

union u_retLen
{
int retLen;
unsigned long ptr;
};
someSetFunc(&u_retLen.ptr);
printf ("ret len = %d/n" ,u_retLen.retLen);

  雖然會使源代碼變得醜陋,但對於大部分已有的源代碼來說,這可能是改動最小的方案了。而對於新寫的代碼來說,如何更好的設計函數的入口參數(比如使用 void*)可能纔是需要去思考的問題了。


發佈了20 篇原創文章 · 獲贊 5 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章