【问题标题】:`pragma pack(push, 1)` crashes in GCC 4.4.7. Possible compiler bug?`pragma pack(push, 1)` 在 GCC 4.4.7 中崩溃。可能的编译器错误?
【发布时间】:2015-07-27 22:31:55
【问题描述】:

我遇到了一个让我难过的错误。我已将其范围缩小到 GCC(特别是 RHEL Linux,GCC v.4.4.7)中 pragma pack 命令的问题,可以在下面显示的小示例案例中重新创建。在这种情况下,GCC 似乎正在计算错误的偏移量,这将表现为循环内的崩溃。删除 pragma 包也消除了错误 - 但在实际应用程序中,这将导致许多额外的 GB 内存使用,并且是不可取的。

在下面的示例中,您需要在启用优化 (O3) 的情况下进行编译才能遇到故障。我还在结构中提供了一个可以删除的示例项目(cMagic),这将改变结构对齐并防止触发错误。

我查看了生成的程序集,并认为这可能是编译器错误。我还缺少其他东西吗?任何人都可以确认此错误或提供任何见解吗?

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;
}

生成文件:

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

反汇编图(生成的 ASM 代码):

【问题讨论】:

  • 那是一个旧的编译器...您是否尝试过使用较新的版本来查看错误是否仍然存在?
  • 为了记录,问题是对齐的 SSE movdqa .. 偏移量可能很好。我想优化器认为数组是对齐的,但是包装却没有对齐。
  • 确实,自动矢量化器似乎正在矢量化循环,但效果不佳。关闭它可能会修复崩溃。
  • GCC 5.2 优化了循环输出,因为它没有被使用。添加volatile 它使用了MOV 指令的展开序列,这些指令同样不易受到影响。将 MAGICCONSTANT 增加到 129 会产生一个循环,但仍会使用 MOV 指令,因此不会出现问题。
  • @Jester 谢谢,这是非常有价值的反馈。该代码适用于锁定到 RHEL 版本的企业客户端 - 所以我不确定我是否能够升级 GCC 专业。我将开始进一步研究。

标签: c++ gcc pragma gcc4


【解决方案1】:

看看使用__attribute__ ((packed)); 而不是#pragma pack(1)。 IIRC,这个版本的 GCC 对待它有点不同。

【讨论】:

  • 这似乎解决了这种情况下的问题,尽管我不确定这是否与#pragma 具有相同的效果。从文档中,“附加到枚举、结构或联合类型定义的此属性指定了用于表示该类型所需的最小内存。”。
  • 好点。我很好奇,稍后尝试通过反汇编程序运行它,看看有什么变化。
猜你喜欢
  • 2016-01-30
  • 1970-01-01
  • 1970-01-01
  • 2015-11-25
  • 2016-04-28
  • 1970-01-01
  • 1970-01-01
  • 2015-03-24
相关资源
最近更新 更多