https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81977
Bug ID: 81977 Summary: Possible issue with inline memcpy with packed structures Product: gcc Version: 6.3.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: vvarada at codeaurora dot org Target Milestone: --- g++ -DOUTER bug.cc -Wall -Wextra -fno-strict-aliasing -fwrapv The following source yields different results when building with and without optimizations (-O2). Compiling source did not result in any warnings. Without: optimizations it prints 0xabcd which is expected With -O2 optimization it prints 0x1617 The issue appears to be due to incorrect offsets being computed for the relevant fields resulting from the inlining of memcpy. If you look at the disassembly with -O2 the %edi argument on X64 is set to a constant 0x1617 (5655 decimal) indicating the bug is at the compiler optimizer itself. By changing the size of *uint16_t header_info[2];* one gets different results with -O2 as it picks different portions of _prefz.z for _pref.x. Thanks, -Vijay --------------------------------------------------------------- #include <iostream> #include <cstdint> #include <cstring> using namespace std; void printval(int x) __attribute__((noinline)); void printval(int x) { cout << hex << x << endl; } #define PACKED __attribute__((packed, aligned(1))) typedef struct { uint16_t x ; uint16_t y ; uint64_t z ; } PACKED TestMsgType; struct Payload { uint16_t header_info[2]; TestMsgType _pref; void Pack(uint8_t *buffer) { memcpy(buffer, &_pref, sizeof(_pref)); } void UnPack(uint8_t *buffer) { memcpy(&_pref, buffer, sizeof(_pref)); } }; struct Msg { Payload _payload; void Pack(uint8_t *buffer) { _payload.Pack(buffer); } void UnPack(uint8_t *buffer) { _payload.UnPack(buffer); } }; int main() { uint8_t * buffer = new uint8_t [30]; Msg msg; Msg msg1; msg._payload._pref.x = 0xabcd; msg._payload._pref.y = 0xa; msg._payload._pref.z = 0x0001020304051617; msg.Pack(&buffer[0]); msg1.UnPack(&buffer[0]); printval(msg1._payload._pref.x); delete [] buffer; }