math.hをインクルードして数学関数を使う場合にgccだけでコンパイルできない本当の理由は?? その2

かぼちゃさんよりコメントを頂いて、前々回くらいにやったタイトルのテーマを検証頂きました。

かぼちゃさんのページ

Blue Sparrow
通信編目
検証ページ

コンパイルのオプションでの切り分けは全くその発想はなかったです。
かぼちゃさんのブログを見てて、なんとなくstraceを思い出したのでやってみた。

ていうかコマンドを知ってるだけで内容は全然分かりません。
でもかぼちゃさんの予測でもlibmとか出てたので全く見当はずれでもないと思うんだ。

結果をダイジェストでどうぞ。

前ふりとして、まずは定数版プログラムを用意

$ gcc kencho2.c -o teisu -Wall

続いて変数版を最適化したものと正規?の-lmをつけてコンパイリます。

gcc kencho.c -o hensu3 -Wall -O3
gcc kencho.c -o hensuseiki -Wall -lm

こちらの環境でもコンパイルは問題なかったです。
リポジトリはSLで、gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)です。
ではstraceで動きを見てみます。openに注目してみてください。

$ strace ./teisu
execve("./teisu", ["./teisu"], [/* 21 vars */]) = 0
brk(0)                                  = 0x10a9000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f821d16f000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=14638, ...}) = 0
mmap(NULL, 14638, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f821d16b000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY)      = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0000\356\1\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1921216, ...}) = 0
mmap(NULL, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f821cbbd000
mprotect(0x7f821cd48000, 2093056, PROT_NONE) = 0
mmap(0x7f821cf47000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18a000) = 0x7f821cf47000
mmap(0x7f821cf4c000, 18696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f821cf4c000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f821d16a000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f821d169000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f821d168000
arch_prctl(ARCH_SET_FS, 0x7f821d169700) = 0
mprotect(0x7f821cf47000, 16384, PROT_READ) = 0
mprotect(0x7f821d170000, 4096, PROT_READ) = 0
munmap(0x7f821d16b000, 14638)           = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f821d16e000
write(1, "10.000\n", 710.000
)                 = 7
exit_group(0)                           = ?
$ strace ./hensu3
execve("./hensu3", ["./hensu3"], [/* 21 vars */]) = 0
brk(0)                                  = 0x242b000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fac367be000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=14638, ...}) = 0
mmap(NULL, 14638, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fac367ba000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY)      = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0000\356\1\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1921216, ...}) = 0
mmap(NULL, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fac3620c000
mprotect(0x7fac36397000, 2093056, PROT_NONE) = 0
mmap(0x7fac36596000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18a000) = 0x7fac36596000
mmap(0x7fac3659b000, 18696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fac3659b000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fac367b9000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fac367b8000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fac367b7000
arch_prctl(ARCH_SET_FS, 0x7fac367b8700) = 0
mprotect(0x7fac36596000, 16384, PROT_READ) = 0
mprotect(0x7fac367bf000, 4096, PROT_READ) = 0
munmap(0x7fac367ba000, 14638)           = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fac367bd000
write(1, "10.000\n", 710.000
)                 = 7
exit_group(0)                           = ?
$ strace ./hensuseiki
execve("./hensuseiki", ["./hensuseiki"], [/* 21 vars */]) = 0
brk(0)                                  = 0x17bf000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb9bbe1a000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=14638, ...}) = 0
mmap(NULL, 14638, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fb9bbe16000
close(3)                                = 0
open("/lib64/libm.so.6", O_RDONLY)      = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p>\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=596264, ...}) = 0
mmap(NULL, 2633912, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb9bb978000
mprotect(0x7fb9bb9fb000, 2093056, PROT_NONE) = 0
mmap(0x7fb9bbbfa000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x82000) = 0x7fb9bbbfa000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY)      = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0000\356\1\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1921216, ...}) = 0
mmap(NULL, 3750152, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb9bb5e4000
mprotect(0x7fb9bb76f000, 2093056, PROT_NONE) = 0
mmap(0x7fb9bb96e000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18a000) = 0x7fb9bb96e000
mmap(0x7fb9bb973000, 18696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fb9bb973000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb9bbe15000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb9bbe14000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb9bbe13000
arch_prctl(ARCH_SET_FS, 0x7fb9bbe14700) = 0
mprotect(0x7fb9bb96e000, 16384, PROT_READ) = 0
mprotect(0x7fb9bbbfa000, 4096, PROT_READ) = 0
mprotect(0x7fb9bbe1b000, 4096, PROT_READ) = 0
munmap(0x7fb9bbe16000, 14638)           = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb9bbe19000
write(1, "10.000\n", 710.000
)                 = 7
exit_group(0)                           = ?

ここで確認できたのが-lmでコンパイルしたものだけ/lib64/libm.so.6を呼び出していて、定数のものと変数を最適化したものは/lib64/libc.so.6の呼び出しだけで実行できている様子。

となると、かぼちゃさんの検証結果から。

引数に定数を入れたときバイナリに計算結果のみが反映され,オブジェクトファイルを無視する

ってことは、libcだけで実行できるから-lmはいらない。libmを呼び出す必要があるからエラー吐いてるよってことかな。

オブジェクトファイルというものも知らないし、イメージで言ってるので、見当はずれなことを言ってたらごめんなさいね。

 

柴田望洋さんの本もやっとこさ中級編に入って、いろいろおもしろそうです。