代码之家  ›  专栏  ›  技术社区  ›  Bruno Rijsman

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

  •  17
  • Bruno Rijsman  · 技术社区  · 17 年前

    我有以下程序:

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

    我正在使用运行在多CPU 64位Intel计算机上的Linux上的GCC4.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位库链接?

    2 回复  |  直到 17 年前
        1
  •  15
  •   Dan Udey    17 年前

    GCC page on Atomic Builtins :

    并非所有操作都支持 所有目标处理器。如果某一特定 无法在上实现操作 目标处理器,将发出警告 生成并调用外部 将生成函数。这个 外部功能也一样 名为builtin,带有 附加后缀“u n”,其中n是 数据类型的大小。

    从编译器输出判断,它指 __sync_add_and_fetch_4 ,这就是发生的事情。出于某种原因,gcc没有正确地生成外部函数。

    这很可能就是为什么在32位模式下只会出现错误的原因——在64位模式下编译时,它会更紧密地为处理器编译。当为32位编译时,它很可能使用了一个不支持这些特性的通用arch(例如i386)。尝试通过-mcpu为您的芯片系列(Xeon、Core2等)指定一个特定的体系结构,看看是否有效。

    如果没有,那么您必须弄清楚为什么gcc没有包含它应该生成的适当函数。

        2
  •  24
  •   Bruno Rijsman    17 年前

    丹·乌迪的回答很接近,实际上足够接近,让我找到真正的解决办法。

    根据手册页,“-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