2

I have a line in some legacy's source code:

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

This yields the following warning:

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

How can I get rid of this warning ?

my compile line:

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)
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
Patryk
  • 22,602
  • 44
  • 128
  • 244
  • Use compiler option `-fno-strict-aliasing`. This code violates the standard and in -O3 mode gcc might optimize it out entirely , however the `-fno-strict-aliasing` option causes it to behave as if you want to access the memory in the char buffer. – M.M Aug 28 '14 at 10:38
  • 1
    You could also consider fixing the code, e.g. `unsigned int msgLength; memcpy(&msgLength, m_recvBuf, sizeof msgLength); msgLength = ntohl(msgLength);`, or even better, do a portable conversion – M.M Aug 28 '14 at 10:40

2 Answers2

3

The problem with your code is that violates strict aliasing rules and thus it's potentially unsafe.

You can either hide the warning with -Wno-strict-aliasing (this won't solve your problem), modify your data structure or avoid the problem entirely by specifying position and length of your binary copy as Matt suggested (probably the best option):

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

Notice: I've not been getting the error with clang 3.4 and gcc 4.8.2 in -O3, that means the compiler might have optimized the warning away. Anyway that doesn't assure you your code is safe.

Ofek Shilon
  • 14,734
  • 5
  • 67
  • 101
Marco A.
  • 43,032
  • 26
  • 132
  • 246
  • I personally prefer to [this article](http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html) on strict aliasing to the QT one. – Shafik Yaghmour Aug 28 '14 at 16:52
  • Also note, as I mention in my [answer here](http://stackoverflow.com/a/25118277/1708801) the strict aliasing checks are not guaranteed to catch strict aliasing violations. So no warning does not mean anything. – Shafik Yaghmour Aug 28 '14 at 16:54
2

As the previous responders have said you can alter the compile flags to make the warning go away. If you're open to a little light refactoring though, you can solve the issue more cleanly with a union like this:

#define MAXMSG 1024

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

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

unsigned int msgLength = ntohl(recvbuf.length);
Andy Brown
  • 11,766
  • 2
  • 42
  • 61
  • Note that type punning through a union is technically undefined behavior in C++ but most compiler support it. You can learn a bit more in [my answer here](http://stackoverflow.com/a/20956250/1708801). – Shafik Yaghmour Aug 28 '14 at 16:50