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

中文警告:提領類型雙關的指針將破壞強重疊規則

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 參數的說明是:Allowsthe compiler to assume the strictest aliasing rules applicable tothe language being compiled.  For C (and C++),this activates optimizations based on the type ofexpressions.  In particular, an object of one typeis assumed never to reside at the same address as an object of adifferent type, unless the types are almost thesame.  For example, an "unsigned int" can alias an"int", but not a "void*" or a "double".  Acharacter type may alias any other type.

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

int retLen;
someSetFunc((unsignedlong*)&retLen);
printf("ret len= %d\n",retLen);

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

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

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

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


轉自:http://www.zeali.net/entry/454


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章