32 ビット モードで gcc アトミック操作をコンパイルするとリンク エラーが発生する
質問
次のプログラムがあります。
~/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 ビット実行可能ファイルが必要です。
私の2つの質問は次のとおりです。
32 ビット モードでコンパイルするとリンク エラーが発生するのはなぜですか?
32 ビット ライブラリとリンクしながら、プログラムをコンパイルしてリンクできるようにする方法はありますか?
解決
から Atomic Builtins に関する GCC ページ:
すべての操作がすべてのターゲットプロセッサでサポートされているわけではありません。ターゲットプロセッサに特定の操作を実装できない場合、警告が生成され、呼び出しが外部関数が生成されます。外部関数はビルトインと同じ名前を持ち、追加の接尾辞「_n」があり、nはデータ型のサイズです。
コンパイラの出力から判断すると、これは次のことを指します __sync_add_and_fetch_4
, 、これが起こっていることです。何らかの理由で、GCC は外部関数を適切に生成していません。
これが、32 ビット モードでのみエラーが発生する理由である可能性があります。64 ビット モードでコンパイルすると、プロセッサに合わせてより正確にコンパイルされます。32 ビット用にコンパイルする場合、これらの機能をネイティブにサポートしていない汎用アーキテクチャ (i386 など) が使用される可能性があります。-mcpu を使用してチップ ファミリ (Xeon、Core 2 など) の特定のアーキテクチャを指定して、それが機能するかどうかを確認してください。
そうでない場合は、GCC が生成すべき適切な関数が含まれていない理由を理解する必要があります。
他のヒント
Dan Udey からの答えは、私が本当の解決策を見つけることができるほど近いものでした。
man ページによると、「-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