27.2. strace によって brk() / malloc() のコールをチェック

それで brk() はどこで使われるの?

まあ疑問は出てくるでしょうが(色々とやばそうだから) brk() は malloc に任せようという筆者のスタンスからすると説明が難しくなります。

視点を変えていつ malloc() が brk() をコールするのかというのは strace コマンドを使えばできます。

strace コマンドはシステムコールをトラック(捕捉)してくれるんですから、ログを見ていけば brk() が見つかるはずです。

ではやって見ましょう。

$ strace ./a.out
execve("./a.out", ["./a.out"], 0x7ffcf75c2290 /* 57 vars */) = 0
brk(NULL)                               = 0x55d7d45c9000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/komatsu/stderred/build/libstderred.so", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\23\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=23280, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff01531e000
mmap(NULL, 2113992, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ff014ef4000
mprotect(0x7ff014ef8000, 2093056, PROT_NONE) = 0
mmap(0x7ff0150f7000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x3000) = 0x7ff0150f7000
close(3)                                = 0
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=127214, ...}) = 0
mmap(NULL, 127214, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff0152fe000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260\34\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
mmap(NULL, 4131552, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ff014b03000
mprotect(0x7ff014cea000, 2097152, PROT_NONE) = 0
mmap(0x7ff014eea000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7ff014eea000
mmap(0x7ff014ef0000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ff014ef0000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\16\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=14560, ...}) = 0
mmap(NULL, 2109712, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7ff0148ff000
mprotect(0x7ff014902000, 2093056, PROT_NONE) = 0
mmap(0x7ff014b01000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7ff014b01000
close(3)                                = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff0152fb000
arch_prctl(ARCH_SET_FS, 0x7ff0152fb740) = 0
mprotect(0x7ff014eea000, 16384, PROT_READ) = 0
mprotect(0x7ff014b01000, 4096, PROT_READ) = 0
mprotect(0x7ff0150f7000, 4096, PROT_READ) = 0
mprotect(0x55d7d4512000, 4096, PROT_READ) = 0
mprotect(0x7ff015320000, 4096, PROT_READ) = 0
munmap(0x7ff0152fe000, 127214)          = 0
ioctl(2, TCGETS, {B38400 opost isig icanon echo ...}) = 0
brk(NULL)                               = 0x55d7d45c9000
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
brk(0x55d7d45ea000)                     = 0x55d7d45ea000
write(1, "initial sbrk: 0x55d7d45c9000\n", 29initial sbrk: 0x55d7d45c9000
) = 29
write(1, "malloc address: 0x55d7d45c9670\n", 31malloc address: 0x55d7d45c9670
) = 31
write(1, "second sbrk: 0x55d7d45ea000\n", 28second sbrk: 0x55d7d45ea000
) = 28
mmap(NULL, 33558528, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff0128fe000
write(1, "malloc address: 0x7ff0128fe010\n", 31malloc address: 0x7ff0128fe010
) = 31
write(1, "third sbrk: 0x55d7d45ea000\n", 27third sbrk: 0x55d7d45ea000
) = 27
mmap(NULL, 34359742464, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)
brk(0x55dfd45ea000)                     = 0x55d7d45ea000
mmap(NULL, 34359873536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)
write(2, "\33[31m", 5)                  = 5
write(2, "allocation error v: Cannot alloc"..., 43allocation error v: Cannot allocate memory
) = 43
write(2, "\33[0m", 4)                   = 4
write(1, "final sbrk: 0x55d7d45ea000\n", 27final sbrk: 0x55d7d45ea000
) = 27
munmap(0x7ff0128fe000, 33558528)        = 0
exit_group(0)                           = ?
+++ exited with 0 +++

malloc で割り当てした部分は以下のように brk() によってヒープ領域が拡張されてます。

brk(NULL)                               = 0x55d7d45c9000
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
brk(0x55d7d45ea000)                     = 0x55d7d45ea000

さらに 128KiB 以上の割り当てをした際に brk() の代わりに mmap() が使われています。

mmap(NULL, 33558528, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff0128fe000
write(1, "malloc address: 0x7ff0128fe010\n", 31malloc address: 0x7ff0128fe010
) = 31
write(1, "third sbrk: 0x55d7d45ea000\n", 27third sbrk: 0x55d7d45ea000
) = 27

該当する行を探すのが難しいと思いますが、下から上に10行程度に目を戻せば分かるんじゃないですかね。

Copyright 2018-2019, by Masaki Komatsu