在32位模式下编译gcc原子操作时出现链接错误

时间:2020-03-06 14:41:50  来源:igfitidea点击:

我有以下程序:

~/test> cat test.cc
int main()
{
  int i = 3;
  int j = __sync_add_and_fetch(&i, 1);
  return 0;
}

我正在在多CPU 64位Intel计算机上运行的Linux上使用GCC 4.2.2编译此程序:

~/test> uname --all
Linux doom 2.6.9-67.ELsmp #1 SMP Wed Nov 7 13:56:44 EST 2007 x86_64 x86_64 x86_64 GNU/Linux

当我以64位模式编译程序时,它可以正常编译和链接:

~/test> /share/tools/gcc-4.2.2/bin/g++ test.cc
~/test>

当我以32位模式进行编译时,出现以下错误:

~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 test.cc
/tmp/ccEVHGkB.o(.text+0x27): In function `main':
: undefined reference to `__sync_add_and_fetch_4'
collect2: ld returned 1 exit status
~/test>

尽管我永远不会真正在32位处理器上运行,但是我确实需要32位可执行文件,因此可以链接某些32位库。

我的两个问题是:

  • 在32位模式下进行编译时,为什么会出现链接错误?
  • 有什么方法可以使程序进行编译和链接,同时仍然可以与32位库链接?

解决方案

在"原子内建函数"的" GCC"页面上:

Not all operations are supported by
  all target processors. If a particular
  operation cannot be implemented on the
  target processor, a warning will be
  generated and a call an external
  function will be generated. The
  external function will carry the same
  name as the builtin, with an
  additional suffix `_n' where n is the
  size of the data type.

从引用__sync_add_and_fetch_4的编译器输出来看,这就是正在发生的情况。由于某些原因,GCC无法正确生成外部功能。

这很可能就是为什么在为64位模式进行编译时仅在32位模式下出现错误的原因,它会更紧密地为处理器编译。当编译为32位时,很可能使用的是本机不支持这些功能的通用体系结构(例如i386)。尝试通过-mcpu为芯片系列(Xeon,Core 2等)指定特定的体系结构,看看是否可行。

如果没有,我们将不得不弄清楚为什么GCC没有包括它应该生成的适当功能。

丹·乌迪(Dan Udey)的回答很接近,实际上已经足够接近,使我能够找到真正的解决方案。

根据手册页,"-mcpu"是" -mtune"的已弃用同义词,仅表示"针对特定CPU进行优化(但仍在较旧的CPU上运行,尽管优化程度较低)"。我试过了,但并没有解决问题。

但是,"-march ="表示"为特定CPU生成代码(并且不能在较旧的CPU上运行)"。当我尝试这样做时,它解决了问题:指定i486或者更好的CPU摆脱了链接错误。

~/test> /share/tools/gcc-4.2.2/bin/g++ -m32  test.cc
/tmp/ccYnYLj6.o(.text+0x27): In function `main':
: undefined reference to `__sync_add_and_fetch_4'
collect2: ld returned 1 exit status

~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 -march=i386 test.cc
/tmp/ccOr3ww8.o(.text+0x22): In function `main':
: undefined reference to `__sync_add_and_fetch_4'
collect2: ld returned 1 exit status

~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 -march=i486 test.cc

~/test> /share/tools/gcc-4.2.2/bin/g++ -m32 -march=pentium test.cc