题
我有以下程序:
~/test> cat test.cc
int main()
{
int i = 3;
int j = __sync_add_and_fetch(&i, 1);
return 0;
}
我正在使用GCC 4.2.2在多CPU 64位Intel机器上运行的Linux上编译这个程序:
~/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的Atomic页面建宏的:
并非所有操作都受支持 所有目标处理器。如果特别的话 操作无法实施 目标处理器,将发出警告 生成并调用外部 将生成功能。该 外部功能将携带相同 名称为内置,带有 附加后缀`_n',其中n是 数据类型的大小。
从您的编译器输出(参考 __ sync_add_and_fetch_4
)判断,这就是正在发生的事情。由于某种原因,GCC没有正确生成外部功能。
这可能是您在32位模式下只出现错误的原因 - 在编译64位模式时,它会更紧密地编译处理器。在编译32位时,它可能正在使用通用的arch(例如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