log10(x)はmath.hをインクルードしなければ使えない関数である。
#include <stdio.h>
#include <math.h>
void main() {
double x = 100;
x = log10(x);
printf("%f\n",x);
return ;
}
これを端末で次のようにコンパイルしようとすると、
gcc -o test test.c
以下のエラーが出て失敗する。
`log10' に対する定義されていない参照です
これは必要なライブラリとのリンクができなかったために起こる。
なので、引数-lを使って使うライブラリを指定する必要がある。
ここではlibm.aが必要なので次のどちらかのようにしてコンパイルすると、エラーは出ない。
gcc -o test test.c -lm
gcc test.c -lm -o test
ただし、順番を変えて次の場合はエラーが出て失敗する。
gcc -o test -lm test.c
gcc -lm -o test test.c
gcc -lm test.c -o test
一応、オブジェクトファイルを作ってから試してみたが、結果は同じ。
test.cよりも-lmが後に無いとダメらしい。
読み込んだ順番に処理するため、libm.aより後に読み込まれたものは関数が組み込まれないんだとか。(GCCコマンド・オプションのリンク処理用のオプションを参照。)
私のように「引数-lm入れればいいんでしょ〜」ぐらいの感覚で使ってしまうと、ドツボにハマるので気をつけましょう・・・・
ライブラリのことを調べていたら、依存関係を調べるコマンドを発見。
実行ファイルのライブラリの依存関係を調べるにはlddコマンドを利用するらしい。
ldd -v xxxx xxxxは実行ファイルオプション-vは詳細情報の追加
とすることで、リンクしている共有ライブラリを検索できる。
試した結果。
$ ldd test
linux-gate.so.1 => (0xb77cd000)
libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0xb7771000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75c3000)
/lib/ld-linux.so.2 (0xb77d0000)
意味しているところは、testを実行するにあたり、
linux-gate.so.1
libm.so.6
libc.so.6
/lib/ld-linux.so.2
という共有ライブラリが必要であり、「=>」の後のパスは実際にリンクされたライブラリ。
「リンクさせたのはlibm.aじゃなかったの?」と思ってライブラリの場所を、
sudo find / -name "libm.a" -ls
で探してみたら
/usr/lib/i386-linux-gnu/libm.a
にあった。ARアーカイブらしい。
同じディレクトリに共有ライブラリlibm.soのリンクも発見。上記のアドレスはそのリンク元の模様。
何らかの処理でこうなっているのだろうが、よくわからん。
/usr/lib/i386-linux-gnu/libm.a
にあった。ARアーカイブらしい。
同じディレクトリに共有ライブラリlibm.soのリンクも発見。上記のアドレスはそのリンク元の模様。
何らかの処理でこうなっているのだろうが、よくわからん。
ちなみに、lddでコマンドは/binディレクトリに入って調べると、各コマンドに必要なライブラリを調べることができるようだ。
0 件のコメント:
コメントを投稿