c++gccpragmagcc4

`pragma pack(push, 1)` crashes in GCC 4.4.7. Possible compiler bug?


I'm encountering a bug that has me stumped. I've narrowed it down to an issue with the pragma pack command in GCC (specifically RHEL Linux, GCC v.4.4.7) that can be recreated in the small sample case I've shown below. It looks like GCC is computing the wrong offset in this case, which will manifest itself as a crash within the loop. Removing the pragma pack also removes the fault - but in the real application this will cause many additional gigabytes of memory use and is not desirable.

In the example below, you will need to compile with optimizations enabled (O3) to experience the failure. I've also provided an example item (cMagic) in the structure that can be removed which will change the structure alignment and keep the bug from triggering.

I've taken a look at the generated assembly and believe this may be a compiler bug. Am I missing something else? Can anyone confirm this bug or provide any insights?

Crash.cpp:

/*  Platform Version Info:
 *     gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)
 *     uname: 2.6.32-504.16.2.el6.x86_64 #1 SMP Tue Mar 10 17:01:00 EDT 2015 x86_64 x86_64 x86_64 GNU/Linux
 *
 *  Compiling:
 *     Must use -O3 for compiling and linking
 *     CXX= g++ -g -O3 -fPIC -rdynamic -Wall -Wno-deprecated -DDEBUG
 *     CPP= g++ -g -O3 -fPIC -rdynamic -Wall -Wno-deprecated -DDEBUG
 *
 *  Notes:
 *     This appears to be an optimization and alignment issue.
 *     Getting rid of a byte in Place (cMagic) causes the program to complete successfully.
 *
 */


#include <stdlib.h>
#include <iostream>

using namespace std;

#pragma pack(push,1)  // Structures must be packed tightly
#define MAGICCONSTANT 17

struct Place {
   int iFoo;
   char cMagic;         // GCC doesn't like cMagic.  Disillusion it and everything is OK
   int aiArray[MAGICCONSTANT];
};


#pragma pack(pop)

int main(int argc, const char *argv[])
{
   Place *pPlace = new Place;   // Place must be on the heap... so new, calloc, malloc, etc

   for (int c = 0; (c < MAGICCONSTANT); c++) {
      pPlace->aiArray[c] = 0;
   }

   delete pPlace;

   cout << "Complete!" << endl;
   return 0;
}

Makefile:

CXX= g++ -g -O3 -fPIC -rdynamic -Wall -Wno-deprecated -DDEBUG
CPP= g++ -g -O3 -fPIC -rdynamic -Wall -Wno-deprecated -DDEBUG

OBJS=   Crash.o
SRCS=   Crash.cpp
TARG=   crash

debug:: ${TARG}

all:: ${TARG}

${TARG}: ${OBJS}
        ${CPP} -o ${TARG} ${OBJS} ${LDFLAGS} ${LIBS}

clean::
        rm -f ${TARG} ${OBJS} ${TARG}.core core

Disassembly Graph (Generated ASM Code):

Disassembly graph


Solution

  • Look at using __attribute__ ((packed)); instead of #pragma pack(1). IIRC, this version of GCC treats it a bit differently.