LDCはバックエンドがLLVMであるので、sanitizerの機能が一部使える。
一応 address
, fuzzer
, memory
, thread
とあるけれど、手元のLDC 1.4.0でまともに使うことができたのはThreadSanitizerのみであった。
AddressSanitizer
asan/outofbounds.d
void main() { auto arr = [0, 1, 2, 3]; auto y = arr.ptr + 4; }
これLeakSanitizerでひっかかってるけど、どうなんだ。
(ldc-1.4.0)$ ( cd asan && ldc2 -fsanitize=address -boundscheck=off outofbounds.d && ./outofbounds ) ================================================================= ==7758==ERROR: LeakSanitizer: detected memory leaks Direct leak of 72 byte(s) in 1 object(s) allocated from: #0 0x55ecd0e3f5b0 (/home/kubo39/dev/dlang/ldc-san/asan/outofbounds+0xb75b0) #1 0x55ecd0e87ddc (/home/kubo39/dev/dlang/ldc-san/asan/outofbounds+0xffddc) Direct leak of 16 byte(s) in 1 object(s) allocated from: #0 0x55ecd0e3f3b8 (/home/kubo39/dev/dlang/ldc-san/asan/outofbounds+0xb73b8) #1 0x55ecd0e8876a (/home/kubo39/dev/dlang/ldc-san/asan/outofbounds+0x10076a) #2 0x55ecd0d9b5e4 (/home/kubo39/dev/dlang/ldc-san/asan/outofbounds+0x135e4) SUMMARY: AddressSanitizer: 88 byte(s) leaked in 2 allocation(s).
どうやらGCが入るとそもそもLeakSanitizerでひっかかるのでだめらしい。
void main()
{
}
(ldc-1.4.0)$ ( cd asan && ldc2 -fsanitize=address emptymain.d && ./emptymain ) ================================================================= ==19717==ERROR: LeakSanitizer: detected memory leaks Direct leak of 72 byte(s) in 1 object(s) allocated from: #0 0x55934f6ffd90 (/home/kubo39/dev/dlang/ldc-san/asan/emptymain+0xb2d90) #1 0x55934f74cafc (/home/kubo39/dev/dlang/ldc-san/asan/emptymain+0xffafc) Direct leak of 16 byte(s) in 1 object(s) allocated from: #0 0x55934f6ffb98 (/home/kubo39/dev/dlang/ldc-san/asan/emptymain+0xb2b98) #1 0x55934f74d48a (/home/kubo39/dev/dlang/ldc-san/asan/emptymain+0x10048a) #2 0x55934f660304 (/home/kubo39/dev/dlang/ldc-san/asan/emptymain+0x13304) SUMMARY: AddressSanitizer: 88 byte(s) leaked in 2 allocation(s).
それでは、とGCを外してみるとAddressSantizerはちゃんと動いていないように見受けられる。
extern(C) void main() { int[4] arr = [0, 1, 2, 3]; auto y = arr.ptr + 10; }
(ldc-1.4.0)$ ( cd asan && ldc2 -fsanitize=address outofbounds2.d && ./outofbounds2 ) (ldc-1.4.0)$
結論からいうと、-fsanitize=address
はLeakSanitizerを有効にし、GCを起動するようなプログラムの場合は必ずリーク検出が発生してしまうようだ。
ちなみに -sanitize=memory
の結果は以下のようになった。
(ldc-1.4.0)$ ( cd asan && ldc2 -fsanitize=memory emptymain.d && ./emptymain ) gcc: error: unrecognized argument to -fsanitize= option: ‘memory’ Error: /usr/bin/gcc failed with status: 1
ThreadSanitizer
tsan/datarace.d
import core.thread; __gshared static int ANSWER = 32; void f() { ANSWER = 42; } void main() { auto t = new Thread(&f).start(); ANSWER = 24; t.join(); }
表示は質素だけど、競合条件を判定できている。
(ldc-1.4.0)$ ( cd tsan && ldc2 -fsanitize=thread datarace.d && ./datarace ) FATAL: ThreadSanitizer: unexpected memory mapping 0x56288abe3000-0x56288ac1b000
追記
いろいろ追試したところ、ThreadSanitizerも信頼できない。
(ldc-1.4.0)$ ldc2 -fsanitize=thread emptymain.d (ldc-1.4.0)$ ./emptymain FATAL: ThreadSanitizer: unexpected memory mapping 0x562d389a0000-0x562d389d7000
AddressSanitizerに至っては、いつのまにかリンカエラーでこけるようになっている。
(ldc-1.4.0)$ ( cd asan && ldc2 -fsanitize=address emptymain.d && ./emptymain ) /usr/bin/ld: /home/kubo39/dlang/ldc-1.4.0/lib/libldc_rt.asan-x86_64.a(asan_allocator.cc.o): 誤った再配置シンボル索引 (0x1fd8ca57 >= 0x11f) (オフセット 0x1fd8000000027079、セクション `.debug_loc' 内用) です /usr/bin/ld: /home/kubo39/dlang/ldc-1.4.0/lib/libldc_rt.asan-x86_64.a(asan_allocator.cc.o): 誤った再配置シンボル索引 (0x1fd8ca57 >= 0x11f) (オフセット 0x1fd8000000027079、セクション `.debug_loc' 内用) です /usr/bin/ld: 最終リンクに失敗しました: 不正な値です collect2: error: ld returned 1 exit status Error: /usr/bin/gcc failed with status: 1
GNU ld側の問題な気がするが、追求するのがおっくうになっている。どうせ現時点では使い物にならないだろう。
(ldc-1.4.0)$ ( LANG=C; cd asan && LD_DEBUG=reloc ldc2 -fsanitize=address emptymain.d && ./emptymain ) ... 22218: relocation processing: /usr/lib/gcc/x86_64-linux-gnu/6/liblto_plugin.so 22218: 22218: calling init: /usr/lib/gcc/x86_64-linux-gnu/6/liblto_plugin.so 22218: /usr/bin/ld: /home/kubo39/dlang/ldc-1.4.0/lib/libldc_rt.asan-x86_64.a(asan_allocator.cc.o): bad reloc symbol index (0x1fd8ca57 >= 0x11f) for offset 0x1fd8000000027079 in section `.debug_loc' /usr/bin/ld: /home/kubo39/dlang/ldc-1.4.0/lib/libldc_rt.asan-x86_64.a(asan_allocator.cc.o): bad reloc symbol index (0x1fd8ca57 >= 0x11f) for offset 0x1fd8000000027079 in section `.debug_loc' /usr/bin/ld: final link failed: Bad value 22218: 22218: calling fini: /usr/lib/gcc/x86_64-linux-gnu/6/liblto_plugin.so [0] 22218: ...