17

我有以下程序:

~/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 位库。

我的两个问题是:

  1. 为什么在 32 位模式下编译时会出现链接错误?

  2. 有没有办法让程序编译和链接,同时仍然能够与 32 位库链接?

4

2 回答 2

24

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
于 2008-09-25T00:33:39.450 回答
15

Atomic Builtins 的 GCC 页面

并非所有目标处理器都支持所有操作。如果无法在目标处理器上执行特定操作,则会生成警告并调用外部函数。外部函数将与内置函数具有相同的名称,并带有一个附加后缀“_n”,其中 n 是数据类型的大小。

从您的编译器输出来看,它指的是__sync_add_and_fetch_4,这就是正在发生的事情。出于某种原因,GCC 没有正确生成外部函数。

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

如果没有,您将不得不弄清楚为什么 GCC 不包含它应该生成的适当函数。

于 2008-09-25T00:18:46.130 回答