• https://github.com/herumi/misc/blob/master/dev/dea
d-lock.cpp
• ./a.outで返って来ない
•psでa.outのプロセスidをさがす
• sudo gdb -p <プロセスid>
• cat /proc/<プロセスid>/mapsなどで情報いろいろみえる
• info threadでthreadが2個あることがわかる
• t 2で2番目に行きbtでバックトレース
dead lockした実行ファイル(1/2)
(gdb) info thread
Id Target Id Frame
2 Thread 0x7f5b3883b700 (LWP 964) "a.out" ...
1 Thread 0x7f5b3984a780 (LWP 963) "a.out" ...
(gdb) t 2
[Switching to thread 2 (Thread 0x7f5b3883b700 (LWP 964))]
#0 0x00007f5b38f15f1c in __lll_lock_wait () from ...
13/30
14.
• dead-lock.cppの12行目で止まっていた
• straceで呼ばれたシステムコールの確認
•ltraceで呼ばれたライブラリ関数の確認
• アドレスは毎回変わる
• sudo sysctl -w kernel.randomize_va_space=0で固定化
• セキュリティ低下につながるので本番環境では禁止
dead lockした実行ファイル(1/2)
gdb) bt
#0 ...5f1c in __lll_lock_wait () from ...libpthread.so.0
#1 ...1649 in _L_lock_909 () from ... libpthread.so.0
#2 ...1470 in pthread_mutex_lock () from ... libpthread.so.0
#3 ...0ecc in __gthread_mutex_lock (__mutex=0x7ffcec6c3e90) at ...
#4 ...12fa in std::mutex::lock (this=0x7ffcec6c3e90) at ...
#5 ...137e in std::lock_guard<std::mutex>::lock_guard ...
#6 ...0fbf in f (m=...) at dead-lock.cpp:12
#7 ...274f in std::_Bind_simple<void (*(std:...
14/30
• deleteしていない
メモリ解放し忘れ
% catt.cpp
int main()
{
char *p = new char[10];
}
% clang++-3.6 -fsanitize=address no_free.cpp -g && ./a.out
=================================================================
==11320==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 10 byte(s) in 1 object(s) allocated from:
#0 0x4dc4f2 in operator new[](unsigned long) (/a.out+0x4dc4f2)
#1 0x4dd24f in main /no_free.cpp:3:12
#2 0x7fc2af5a4f44 in __libc_start_main /build/eglibc-oGUzwX/eglibc-
2.19/csu/libc-start.c:287
SUMMARY: AddressSanitizer: 10 byte(s) leaked in 1 allocation(s).
19/30
20.
• delete p;
•cf. std::stringかstd::unique_ptr<char> p(new char[10])を使え
delete追加したけど間違ってる
% cat t.cpp
int main() {
char *p = new char[10];
delete p;
}
% clang++-3.6 -fsanitize=address no_free.cpp -g && ./a.out
==11464==ERROR: AddressSanitizer: alloc-dealloc-mismatch (operator new []
vs operator delete) on 0x60200000eff0
#0 0x4dc942 in operator delete(void*) (/a.out+0x4dc942)
#1 0x4dd30a in main /no_free.cpp:4:2
#2 0x7fc0cf759f44 in __libc_start_main /build/eglibc-oGUzwX/eglibc-
2.19/csu/libc-start.c:287
#3 0x435f46 in _start (/a.out+0x435f46)
20/30
21.
• ASanとは別のメモリチェックツール
• ASanとは排他的(ASanありでビルドしたものは動かない)
•特別なコンパイルオプションは不要
• 他の便利なオプション--leak-check=full, --tool=callgrind
Valgrind
% g++ no_free.cpp -g
% valgrind ./a.out
==11471== Memcheck, a memory error detector
==11471== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==11471== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright
info
==11471== Command: ./a.out
==11471==
==11471== Mismatched free() / delete / delete []
==11471== at 0x4C2C2BC: operator delete(void*) (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11471== by 0x40066E: main (no_free.cpp:4)
==11471== Address 0x5a22040 is 0 bytes inside a block of size 10 alloc'd
==11471== at 0x4C2B800: operator new[](unsigned long) (in...
21/30
22.
• 高速なmalloc/free
• http://goog-perftools.sourceforge.net/doc/tcmalloc.html
•リンク時にライブラリを指定する
• LD_PRELOADで指定する
• デバッグ機能も持つ
• apt install libtcmalloc*
• 他にも同様のツールはいろいろある
TCMalloc
% g++ no_free.cpp -g
% env LD_PRELOAD=/usr/lib/libtcmalloc_debug.so ./a.out
memory allocation/deallocation mismatch at 0x13280e0: allocated with new
[] being deallocated with delete
Abort (core dumped)
22/30
23.
• 実行しないでエラーを検出するツール
• ASan,Valgrindは実行時解析
• 商用のものが性能がよいことが多い(ex. Coverity)
• cppcheck ; apt install cppcheck
• Visual Studio の /analyzeとか
• cppcheckでも表示される
• clangに付属のscan-build(Xcodeの静的解析ツール)
静的解析ツール
% cppcheck -enable=all no_free.cpp
Checking no_free.cpp...
[no_free.cpp:4]: (error) Mismatching allocation and deallocation: p
int f(int a) {
if (a != 3 || a != 5) return 4;
return 2;
}
t.cpp(3) : warning C6289: 不適切な演算子です:|| を使用した相互排除は常に 0
でない定数となります。&& を使用しようとしましたか?
23/30