2014-08-28 23 views
2

我在一些遺留的源代碼的行:鑄造焦炭[]到usigned INT給出:提領類型-punned指針將打破嚴格走樣規則

#define MAXMSG 1024 
... 
char m_recvBuf[MAXMSG]; 
unsigned int msgLength = ntohl(*((unsigned int *)m_recvBuf)); 

這產生以下警告:

x.cpp: In member function ‘bool xx::cccc(std::string&)’: 
x.cpp:308: warning: dereferencing type-punned pointer will break strict-aliasing rules 

我該如何擺脫這個警告?

我編譯行:

g++ -c -g -O2 -Wall -DDEBUG_ON -D_VERSION_=\"1.0.0\" `xml2-config --cflags` -I../src -I./common -I. -I../../test/ -o common/xx.o common/xx.cpp 

$ g++ --version 
g++ (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3) 
+0

@MarcoA。請檢查我的更新 – Patryk 2014-08-28 10:35:32

+0

使用編譯器選項'-fno-strict-aliasing'。這段代碼違反了標準,並且在-O3模式下,gcc可能會完全優化它,但是'-fno-strict-aliasing'選項會導致它的行爲就像您要訪問char緩衝區中的內存一樣。 – 2014-08-28 10:38:40

+1

您也可以考慮修復代碼,例如'unsigned int msgLength; memcpy(&msgLength,m_recvBuf,sizeof msgLength); msgLength = ntohl(msgLength);',或者甚至更好,做一個便攜式轉換 – 2014-08-28 10:40:41

回答

3

與您的代碼的問題是,違反了strict aliasing rules,因此它是潛在的不安全。

您可以隱藏警告-Wno-strict-aliasing(這不會解決您的問題),修改您的數據結構或完全避免問題,通過指定二進制副本的位置和長度,如馬特建議的(可能是最好的選擇):

unsigned int msgLength; 
memcpy(&msgLength, m_recvBuf, sizeof(msgLength)); 
msgLength = ntohl(msgLength); 

注意:我沒有已經越來越在-O3鏗鏘3.4和gcc 4.8.2的錯誤,這意味着編譯器可能優化了警告了。無論如何,這並不能保證你的代碼是安全的。

+0

我個人比較喜歡[這篇文章](http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html )嚴格的走樣到QT之一。 – 2014-08-28 16:52:39

+0

另請注意,正如我在[這裏回答](http://stackoverflow.com/a/25118277/1708801)中提到的那樣,嚴格的別名檢查並不能保證能夠發現嚴格的別名違規行爲。所以沒有警告並不意味着什麼。 – 2014-08-28 16:54:55

2

正如前面的響應者所說你可以改變編譯標誌來使警告消失。如果你打算輕微重構一下,你可以通過這樣的聯合來更加乾淨地解決問題:

#define MAXMSG 1024 

union { 
    char buf[MAXMSG]; 
    unsigned int length; 
} recvbuf; 

// [ read your message stream to recvbuf.buf ] 

unsigned int msgLength = ntohl(recvbuf.length); 
+0

請注意,在C++中通過聯合打字的技術上是未定義的行爲,但大多數編譯器都支持它。您可以在[我的答案]中瞭解更多(http://stackoverflow.com/a/20956250/1708801)。 – 2014-08-28 16:50:58

相關問題