SlideShare a Scribd company logo
1 of 30
Download to read offline
C/C++プログラマのための開発ツール
2016/9/8
光成滋生
• (主にLinux上における)プログラム開発、
デバッグ、不具合調査のためのツールの紹介
• 広く浅く
• 同じことを複数の手段で
• キーワードや「できること」を知っていれば後は自分で
概要と目的
2/30
• gcc, clang
• ソース読み
• ag, GNU GLOBAL, Doxygen, callgrind
• デバッグ
• gdb, objdump, c++filt, core dump, addr2line
• メモリチェック
• ASan, Valgrind, TCMalloc
• 静的解析
• cppcheck, scan-build
• 実行時解析
• SystemTap, perf
目次
3/30
• 警告系オプション
• -Wall -Wextra ; 必須
• コンパイラの警告を無視してはいけない
• https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-
Options.html
• -Wnon-virtual-dtor
• -Woverloaded-virtual ; virtualを同名の関数で隠してしまった
• 他に-Weffc++など変わりものも
• clangには全ての警告を表示する-Weverythingがある
• ときどき便利
• -pedantic ; C/C++標準でないGNU拡張を使っていないか
C/C++コンパイル時のオプション(1/2)
4/30
• 最適化オプション
• -Ofast ; 最適化最大
• -march=native ; コンパイル環境のCPUに合わせた最適化
• -DNDEBUG ; assert()マクロの無効化
• デバッグ用オプション
• -g ; シンボル情報がつく(速度に影響はない)
• -g3 ; マクロも見えるようになる
• -S ; アセンブリ出力(生成コードが意図通りか?)
• objdumpによる逆アセンブルも便利
• objdump -CSlw -M intel
• -C ; C++の関数名を見やすくする(demangle)
• -S ; ソースコードを併記
C/C++コンパイル時のオプション(2/2)
5/30
• <vector>のソースを見たいが場所はどこ?
• echo "#include <vector>"|gcc -x c++ -E -|lv
• プロファイルをとる
• -pgオプション
• ただし関数に介入するのでオーバーヘッドあり
• perfやVTune(後述)など別のものがおすすめ
その他
6/30
• GNU GLOBAL
• https://www.gnu.org/software/global/
• 関数が定義されている場所を行ったり来たりできる
• 使い方
• 見たいソースのトップディレクトリでgtags
• 各自のエディタに応じて設定すること
• あとはがんばって:-)
• ag
• 高速なgrep ; grep -Irw 単語 ./
• apt install silversearcher-ag
• highway(https://github.com/tkengo/highway)というのも
• Visual Studioなどの統合環境 一度は触ってみるとよい
ソースコード読み補助ツール
7/30
• ソースコードのドキュメント自動化ツール
• apt install doxygen
• ソースコードのコメントに書くとマニュアルを生成する
• doxygen -gで設定ファイルを作成
• doxygen Doxyfileでhtmlを作成
• コメントのつけ方
• http://www.doxygen.jp/docblocks.html
Doxygen
8/30
• Graphviz
• ものの依存関係を画像表示する
• apt install graphviz
• 関数の呼び出し関係の画像化
• DoxygenのDoxyfileでHAVE_DOT = yes
• callgrind
• 呼び出し回数などを可視化
• apt install kcachegrind
• Valgrind(後述)の一部
• valgrind –tool=callgrind <binary>
• kcachegrind callgrind.out.*
関数呼び出しの可視化
9/30
• 落ちるプログラムをデバッグする
• rで実行して落ちたところでbtでバックトレースをみる
gdb(デバッグツール)
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
int main(int argc, char *argv[]) {
char buf[32];
int n = argc == 1 ? 10 : atoi(argv[1]);
printf("n=%d¥n", n);
memset(buf, 'A', n);
printf("n=%d¥n", n);
printf("buf[%d-1]=%c¥n", n, buf[n - 1]);
}
gcc -g t.cpp
gdb --args ./aout 10000
r
...
Program received signal SIGSEGV, Segmentation fault.
10/30
• s ; ステップ実行(1行ずつ実行する)
• 最適化オプションありではコードの位置がずれることが多い
• 一度コマンドを実行したあと[return]で同じコマンドを実行
• fin ; 関数の中から外に出るまで一気に動く
• n ; 関数の中に入らないでステップ実行
• up/down スタックフレームを登ったり降りたり
• p 変数 ; 変数を表示する
gdbのコマンドいくつか
11/30
• gdbを使わず落ちる場所だけ調べる
• 落ちたときのレジスタ, ip, backtrace, メモリマップなど表示
libSegFault.so
env LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so ¥
SEGFAULT_SIGNALS=all ./a.out 10000
*** Segmentation fault
Register dump:
RAX: 00007ffeb2670fd0 RBX: 0000000000000000 RCX: 00007ffeb2671000
...
Backtrace:
/lib/x86_64-linux-gnu/libc.so.6(memset+0x5d)[0x7f4cf774050d]
./a.out[0x400699]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5)[0x7f4cf76d5f45]
./a.out[0x400569]
12/30
• 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
• 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
• プログラムが異常終了したときの情報を保存したもの
• /proc/sys/kernel/core_patternで保存ファイル名を指定
• 例 : カレントディレクトリにcore.<プロセス名>
• shellでcoreサイズを制限していないか確認
• bashならulimit -a ; tcshならlimit
• 0ならcoreファイルは作られないので設定する
• ulimit -c unlimited / limit coredumpsize unlimited
• SEGVする実行ファイルを実行する
• gdb –c <coreファイル> ./a.outでいつものように操作
core dump
sudo sh -c 'echo core.%p > /proc/sys/kernel/core_pattern'
15/30
• coreファイルが無かったとき最低限の情報
• ip ; SEGVしたときに実行していたコードのアドレス
• libc-2.19.soのip番目をさがす
• 00007f55ac1c650d - 7f55ac13a000 = 0x8c50d
• libcの0x8c50d番目は何の関数か
• addr2lineを使う
• memsetのようだ ; 引数がおかしい?(と推測)
• objdump -Sでもわかる
dmesg
[609339.455455] a.out[1088]: segfault at 7fffa910f130 ip 00007f55ac1c650d
sp 00007fffa910ca08 error 6 in libc-2.19.so[7f55ac13a000+1ba000]
% addr2line -e /lib/x86_64-linux-gnu/libc-2.19.so 0x8c50d
/build/eglibc-oGUzwX/eglibc-2.19/string/../sysdeps/x86_64/memset.S:80
16/30
• Address Sanitizer(ASan)
• メモリ関係のエラーのチェック
• バッファオーバーフロー
• ヒープオーバーフロー
• スタックバッファーオーバーフロー
• メモリリーク
• -fsanitize=addressをつけてコンパイル
メモリ関係
17/30
• ./a.out 32 ; 問題なしだが33を指定すると
実行してみる
% ./a.out 33
n=33
==11277==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffdad25b7a0 at pc
0x0000004a691f bp 0x7ffdad25b650 sp 0x7ffdad25ae08
WRITE of size 33 at 0x7ffdad25b7a0 thread T0
#0 0x4a691e in __asan_memset
...
This frame has 5 object(s):
[32, 36) ''
[48, 52) ''
[64, 72) ''
[96, 128) 'buf'
[160, 164) 'n' <== Memory access at offset 128 partially underflows this variable
SUMMARY: AddressSanitizer: stack-buffer-overflow ??:0 __asan_memset
Shadow bytes around the buggy address:
0x100035a436a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100035a436b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100035a436c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100035a436d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100035a436e0: 00 00 00 00 f1 f1 f1 f1 04 f2 04 f2 00 f2 f2 f2
=>0x100035a436f0: 00 00 00 00[f2]f2 f2 f2 04 f3 f3 f3 00 00 00 00
...
18/30
• deleteしていない
メモリ解放し忘れ
% cat t.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
• 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
• 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
• 高速な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
• 実行しないでエラーを検出するツール
• 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
• Linux kernelの中身を調べるツール
• https://wiki.ubuntu.com/Kernel/Systemtap
• インストール
• sudo apt install systemtap
• シンボル付きのカーネルが必要
• バイナリのインストール方法
• https://wiki.ubuntu.com/Kernel/Systemtap#Where_to_get_de
bug_symbols_for_kernel_X.3F
• 自分でビルド
• https://wiki.ubuntu.com/Kernel/Systemtap#How_do_I_build_a
_debuginfo_kernel_if_one_isn.27t_available.3F
• sudo dpkg -i linux-*.ddeb linux-*.debのあとリブート
SystemTap
24/30
• kernel内の関数の場所を調べる
• write(2)を調べたい
• 内部的にはSyS_write
• fs/read_write.cの514行目にある
• sync(8)したときの流れをみたい
• ext4のwriteまわりの関数は何があるだろう
• なんとなくext4_writepagesを見てみる
使い方
% stap -l 'kernel.function("SyS_write")'
kernel.function("SyS_write@/*/fs/read_write.c:514")
% stap -l 'kernel.function("ext4_write*")'
kernel.function("ext4_write_begin@/*/fs/ext4/inode.c:958")
kernel.function("ext4_write_dquot@/*/fs/ext4/super.c:5032")
...
kernel.function("ext4_writepage_trans_blocks@/*/fs/ext4/inode.c:4888")
kernel.function("ext4_writepages@/*/fs/ext4/inode.c:2473")
25/30
• awkライクなスクリプト言語
• コンパイルして実行できる
• 裏でkernel moduleになってloadされる
• ext4_writepagesが呼ばれたときにpidが自分が指定したコマ
ンドなら関数名と引数とバックトレースを表示する
• .call ; 呼ばれたとき
• pid() ; 今のpid
• $$parms ; 引数
stapスクリプト
>cat a.stp
probe kernel.function("ext4_writepages").call
{
if (pid() != target()) exit()
printf("%s(%s)¥n", probefunc(), $$parms)
print_backtrace()
}
26/30
• -c <command>でコマンド実行
• いろいろ試してみる
syncコマンドを実行してみる
% sudo stap a.stp -c "sync"
ext4_writepages(mapping=0xffff880402e009b0 wbc=0xffff880405a9bc58)
0xffffffff81247f80 : ext4_writepages+0x0/0xdb0 [kernel]
0xffffffff8115e47e : do_writepages+0x1e/0x40 [kernel]
0xffffffff811eaae0 : __writeback_single_inode+0x40/0x2a0 [kernel]
0xffffffff811eb9ca : writeback_sb_inodes+0x26a/0x440 [kernel]
0xffffffff811ebc3f : __writeback_inodes_wb+0x9f/0xd0 [kernel]
0xffffffff811ebef3 : wb_writeback+0x283/0x320 [kernel]
0xffffffff811ed77c : bdi_writeback_workfn+0x11c/0x4a0 [kernel]
0xffffffff81086078 : process_one_work+0x178/0x470 [kernel]
0xffffffff81086e91 : worker_thread+0x121/0x410 [kernel]
0xffffffff8108dc79 : kthread+0xc9/0xe0 [kernel]
0xffffffff8173a3e8 : ret_from_fork+0x58/0x90 [kernel]
27/30
• g++ user-backtrace.cpp -g
• sudo stap user.stp –c “./a.out” | c++filt
• print_ubacktrace
でバックトレース
ユーザランドのバックトレース
probe process("./a.out").function("*").call {
printf("%s -> %s¥n", thread_indent(1), probefunc())
}
probe process("./a.out").function("*").return {
printf("%s <- %s¥n", thread_indent(-1), probefunc())
}
0 a.out(23897): -> main
10 a.out(23897): -> h(int)
26 a.out(23897): -> g(int)
30 a.out(23897): -> f(int)
40 a.out(23897): <- g(int)
42 a.out(23897): -> f(int)
45 a.out(23897): <- g(int)
47 a.out(23897): <- h(int)
48 a.out(23897): -> g(int)
51 a.out(23897): -> f(int)
54 a.out(23897): <- g(int)
56 a.out(23897): -> f(int)
59 a.out(23897): <- g(int)
60 a.out(23897): <- h(int)
62 a.out(23897): <- main
64 a.out(23897): <- 0x7fb394b0cf45
#include <stdio.h>
void f(int x) {
printf("f=%d¥n", x);
}
void g(int x) {
puts("g");
for (int i = 0; i < 2; i++) {
f(x + i);
}
}
void h(int x) {
puts("h");
for (int i = 0; i < 2; i++) {
g((x + i) * (x + i));
}
}
int main(int argc, char *[]) {
h(argc);
}
28/30
• SystemTap Beginners Guide
• https://sourceware.org/systemtap/SystemTap_Beginners_Guide/
• スクリプトの文法
• https://sourceware.org/systemtap/langref/Language_elements.html
• サンプルいろいろ
• https://sourceware.org/systemtap/examples/
• 関数いろいろ
• https://sourceware.org/systemtap/man/
• 例 addrからn個のデータを文字列化 kernel_string_n(addr, n)
• Ftraceというkernelのevent記録ツールもある
• cf. ファイルキャッシュクリアの謎
• http://www.slideshare.net/herumi/kernel-fcachebug
参考文献
29/30
• CPU内部のカウンタを使って詳細な情報を収集
• apt install linux-tools-common
• perf listで取得可能な一覧を表示
• VM上では取得可能なeventは極めて制限される
• perf stat -e <イベント> <実行ファイル>
• sudo perf top ; 現在のkernelの詳細なtopを表示
• IntelのVTuneはこれのGUI版(便利)
perf
List of pre-defined events (to be used in -e):
cpu-cycles OR cycles [Hardware event]
instructions [Hardware event]
cache-references [Hardware event]
cache-misses [Hardware event]
branch-instructions OR branches [Hardware event]
...
30/30

More Related Content

What's hot

ウェーブレット木の世界
ウェーブレット木の世界ウェーブレット木の世界
ウェーブレット木の世界Preferred Networks
 
FPGA+SoC+Linux実践勉強会資料
FPGA+SoC+Linux実践勉強会資料FPGA+SoC+Linux実践勉強会資料
FPGA+SoC+Linux実践勉強会資料一路 川染
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチンyohhoy
 
C++でCプリプロセッサを作ったり速くしたりしたお話
C++でCプリプロセッサを作ったり速くしたりしたお話C++でCプリプロセッサを作ったり速くしたりしたお話
C++でCプリプロセッサを作ったり速くしたりしたお話Kinuko Yasuda
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由kikairoya
 
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門masayoshi takahashi
 
マルチコアを用いた画像処理
マルチコアを用いた画像処理マルチコアを用いた画像処理
マルチコアを用いた画像処理Norishige Fukushima
 
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14Ryo Suzuki
 
Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門Etsuji Nakai
 
冬のLock free祭り safe
冬のLock free祭り safe冬のLock free祭り safe
冬のLock free祭り safeKumazaki Hiroki
 
PFNのML/DL基盤を支えるKubernetesにおける自動化 / DevOpsDays Tokyo 2021
PFNのML/DL基盤を支えるKubernetesにおける自動化 / DevOpsDays Tokyo 2021PFNのML/DL基盤を支えるKubernetesにおける自動化 / DevOpsDays Tokyo 2021
PFNのML/DL基盤を支えるKubernetesにおける自動化 / DevOpsDays Tokyo 2021Preferred Networks
 
暗号技術の実装と数学
暗号技術の実装と数学暗号技術の実装と数学
暗号技術の実装と数学MITSUNARI Shigeo
 
Dockerを支える技術
Dockerを支える技術Dockerを支える技術
Dockerを支える技術Etsuji Nakai
 
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門Norishige Fukushima
 
目grep入門 +解説
目grep入門 +解説目grep入門 +解説
目grep入門 +解説murachue
 
最適輸送の解き方
最適輸送の解き方最適輸送の解き方
最適輸送の解き方joisino
 
Dockerfile を書くためのベストプラクティス解説編
Dockerfile を書くためのベストプラクティス解説編Dockerfile を書くためのベストプラクティス解説編
Dockerfile を書くためのベストプラクティス解説編Masahito Zembutsu
 
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法Takuya Akiba
 

What's hot (20)

ウェーブレット木の世界
ウェーブレット木の世界ウェーブレット木の世界
ウェーブレット木の世界
 
FPGA+SoC+Linux実践勉強会資料
FPGA+SoC+Linux実践勉強会資料FPGA+SoC+Linux実践勉強会資料
FPGA+SoC+Linux実践勉強会資料
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
 
C++でCプリプロセッサを作ったり速くしたりしたお話
C++でCプリプロセッサを作ったり速くしたりしたお話C++でCプリプロセッサを作ったり速くしたりしたお話
C++でCプリプロセッサを作ったり速くしたりしたお話
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
 
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門
 
マルチコアを用いた画像処理
マルチコアを用いた画像処理マルチコアを用いた画像処理
マルチコアを用いた画像処理
 
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14
 
Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門
 
冬のLock free祭り safe
冬のLock free祭り safe冬のLock free祭り safe
冬のLock free祭り safe
 
PFNのML/DL基盤を支えるKubernetesにおける自動化 / DevOpsDays Tokyo 2021
PFNのML/DL基盤を支えるKubernetesにおける自動化 / DevOpsDays Tokyo 2021PFNのML/DL基盤を支えるKubernetesにおける自動化 / DevOpsDays Tokyo 2021
PFNのML/DL基盤を支えるKubernetesにおける自動化 / DevOpsDays Tokyo 2021
 
プログラムを高速化する話
プログラムを高速化する話プログラムを高速化する話
プログラムを高速化する話
 
暗号技術の実装と数学
暗号技術の実装と数学暗号技術の実装と数学
暗号技術の実装と数学
 
Dockerを支える技術
Dockerを支える技術Dockerを支える技術
Dockerを支える技術
 
組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門組み込み関数(intrinsic)によるSIMD入門
組み込み関数(intrinsic)によるSIMD入門
 
目grep入門 +解説
目grep入門 +解説目grep入門 +解説
目grep入門 +解説
 
最適輸送の解き方
最適輸送の解き方最適輸送の解き方
最適輸送の解き方
 
Dockerfile を書くためのベストプラクティス解説編
Dockerfile を書くためのベストプラクティス解説編Dockerfile を書くためのベストプラクティス解説編
Dockerfile を書くためのベストプラクティス解説編
 
プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法プログラミングコンテストでの動的計画法
プログラミングコンテストでの動的計画法
 
レシピの作り方入門
レシピの作り方入門レシピの作り方入門
レシピの作り方入門
 

Similar to C/C++プログラマのための開発ツール

StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件yaegashi
 
Ubuntuで始めるコンテナ技術入門
Ubuntuで始めるコンテナ技術入門Ubuntuで始めるコンテナ技術入門
Ubuntuで始めるコンテナ技術入門Takenori Matsumoto
 
高速な暗号実装のためにしてきたこと
高速な暗号実装のためにしてきたこと高速な暗号実装のためにしてきたこと
高速な暗号実装のためにしてきたことMITSUNARI Shigeo
 
Android デバッグ小ネタ
Android デバッグ小ネタAndroid デバッグ小ネタ
Android デバッグ小ネタl_b__
 
Exploring the x64
Exploring the x64Exploring the x64
Exploring the x64FFRI, Inc.
 
Linux Performance Analysis in 15 minutes
Linux Performance Analysis in 15 minutesLinux Performance Analysis in 15 minutes
Linux Performance Analysis in 15 minutesYohei Azekatsu
 
Xbyakの紹介とその周辺
Xbyakの紹介とその周辺Xbyakの紹介とその周辺
Xbyakの紹介とその周辺MITSUNARI Shigeo
 
ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!Yohei Fushii
 
Lxc cf201207-presen
Lxc cf201207-presenLxc cf201207-presen
Lxc cf201207-presenKouhei Maeda
 
第一回コンテナ情報交換会@関西
第一回コンテナ情報交換会@関西第一回コンテナ情報交換会@関西
第一回コンテナ情報交換会@関西Masahide Yamamoto
 
Docker調査20150704
Docker調査20150704Docker調査20150704
Docker調査20150704HommasSlide
 
MINCS – containers in the shell script
MINCS – containers in the shell scriptMINCS – containers in the shell script
MINCS – containers in the shell scriptMasami Hiramatsu
 
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)inaz2
 
A story of porting OpenBSD/luna88k
A story of porting OpenBSD/luna88kA story of porting OpenBSD/luna88k
A story of porting OpenBSD/luna88kKenji Aoyama
 
Lvmを縮小してみた
Lvmを縮小してみたLvmを縮小してみた
Lvmを縮小してみたkoedoyoshida
 
スタート低レイヤー #0
スタート低レイヤー #0スタート低レイヤー #0
スタート低レイヤー #0Kiwamu Okabe
 
カーネルVm関西その参lt
カーネルVm関西その参ltカーネルVm関西その参lt
カーネルVm関西その参ltcosmo0920
 

Similar to C/C++プログラマのための開発ツール (20)

StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件
 
Ubuntuで始めるコンテナ技術入門
Ubuntuで始めるコンテナ技術入門Ubuntuで始めるコンテナ技術入門
Ubuntuで始めるコンテナ技術入門
 
高速な暗号実装のためにしてきたこと
高速な暗号実装のためにしてきたこと高速な暗号実装のためにしてきたこと
高速な暗号実装のためにしてきたこと
 
Android デバッグ小ネタ
Android デバッグ小ネタAndroid デバッグ小ネタ
Android デバッグ小ネタ
 
Exploring the x64
Exploring the x64Exploring the x64
Exploring the x64
 
Linux Performance Analysis in 15 minutes
Linux Performance Analysis in 15 minutesLinux Performance Analysis in 15 minutes
Linux Performance Analysis in 15 minutes
 
Xbyakの紹介とその周辺
Xbyakの紹介とその周辺Xbyakの紹介とその周辺
Xbyakの紹介とその周辺
 
Slide
SlideSlide
Slide
 
ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!
 
Lxc cf201207-presen
Lxc cf201207-presenLxc cf201207-presen
Lxc cf201207-presen
 
第一回コンテナ情報交換会@関西
第一回コンテナ情報交換会@関西第一回コンテナ情報交換会@関西
第一回コンテナ情報交換会@関西
 
Docker調査20150704
Docker調査20150704Docker調査20150704
Docker調査20150704
 
MINCS – containers in the shell script
MINCS – containers in the shell scriptMINCS – containers in the shell script
MINCS – containers in the shell script
 
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
 
A story of porting OpenBSD/luna88k
A story of porting OpenBSD/luna88kA story of porting OpenBSD/luna88k
A story of porting OpenBSD/luna88k
 
Mincs 日本語版
Mincs 日本語版Mincs 日本語版
Mincs 日本語版
 
Lvmを縮小してみた
Lvmを縮小してみたLvmを縮小してみた
Lvmを縮小してみた
 
スタート低レイヤー #0
スタート低レイヤー #0スタート低レイヤー #0
スタート低レイヤー #0
 
カーネルVm関西その参lt
カーネルVm関西その参ltカーネルVm関西その参lt
カーネルVm関西その参lt
 
about DakotagUI
about DakotagUIabout DakotagUI
about DakotagUI
 

More from MITSUNARI Shigeo

範囲証明つき準同型暗号とその対話的プロトコル
範囲証明つき準同型暗号とその対話的プロトコル範囲証明つき準同型暗号とその対話的プロトコル
範囲証明つき準同型暗号とその対話的プロトコルMITSUNARI Shigeo
 
暗認本読書会13 advanced
暗認本読書会13 advanced暗認本読書会13 advanced
暗認本読書会13 advancedMITSUNARI Shigeo
 
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgenIntel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgenMITSUNARI Shigeo
 
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法MITSUNARI Shigeo
 
WebAssembly向け多倍長演算の実装
WebAssembly向け多倍長演算の実装WebAssembly向け多倍長演算の実装
WebAssembly向け多倍長演算の実装MITSUNARI Shigeo
 
Lifted-ElGamal暗号を用いた任意関数演算の二者間秘密計算プロトコルのmaliciousモデルにおける効率化
Lifted-ElGamal暗号を用いた任意関数演算の二者間秘密計算プロトコルのmaliciousモデルにおける効率化Lifted-ElGamal暗号を用いた任意関数演算の二者間秘密計算プロトコルのmaliciousモデルにおける効率化
Lifted-ElGamal暗号を用いた任意関数演算の二者間秘密計算プロトコルのmaliciousモデルにおける効率化MITSUNARI Shigeo
 
BLS署名の実装とその応用
BLS署名の実装とその応用BLS署名の実装とその応用
BLS署名の実装とその応用MITSUNARI Shigeo
 
LazyFP vulnerabilityの紹介
LazyFP vulnerabilityの紹介LazyFP vulnerabilityの紹介
LazyFP vulnerabilityの紹介MITSUNARI Shigeo
 

More from MITSUNARI Shigeo (20)

範囲証明つき準同型暗号とその対話的プロトコル
範囲証明つき準同型暗号とその対話的プロトコル範囲証明つき準同型暗号とその対話的プロトコル
範囲証明つき準同型暗号とその対話的プロトコル
 
暗認本読書会13 advanced
暗認本読書会13 advanced暗認本読書会13 advanced
暗認本読書会13 advanced
 
暗認本読書会12
暗認本読書会12暗認本読書会12
暗認本読書会12
 
暗認本読書会11
暗認本読書会11暗認本読書会11
暗認本読書会11
 
暗認本読書会10
暗認本読書会10暗認本読書会10
暗認本読書会10
 
暗認本読書会9
暗認本読書会9暗認本読書会9
暗認本読書会9
 
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgenIntel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
 
暗認本読書会8
暗認本読書会8暗認本読書会8
暗認本読書会8
 
暗認本読書会7
暗認本読書会7暗認本読書会7
暗認本読書会7
 
暗認本読書会6
暗認本読書会6暗認本読書会6
暗認本読書会6
 
暗認本読書会5
暗認本読書会5暗認本読書会5
暗認本読書会5
 
暗認本読書会4
暗認本読書会4暗認本読書会4
暗認本読書会4
 
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
深層学習フレームワークにおけるIntel CPU/富岳向け最適化法
 
私とOSSの25年
私とOSSの25年私とOSSの25年
私とOSSの25年
 
WebAssembly向け多倍長演算の実装
WebAssembly向け多倍長演算の実装WebAssembly向け多倍長演算の実装
WebAssembly向け多倍長演算の実装
 
Lifted-ElGamal暗号を用いた任意関数演算の二者間秘密計算プロトコルのmaliciousモデルにおける効率化
Lifted-ElGamal暗号を用いた任意関数演算の二者間秘密計算プロトコルのmaliciousモデルにおける効率化Lifted-ElGamal暗号を用いた任意関数演算の二者間秘密計算プロトコルのmaliciousモデルにおける効率化
Lifted-ElGamal暗号を用いた任意関数演算の二者間秘密計算プロトコルのmaliciousモデルにおける効率化
 
楕円曲線と暗号
楕円曲線と暗号楕円曲線と暗号
楕円曲線と暗号
 
HPC Phys-20201203
HPC Phys-20201203HPC Phys-20201203
HPC Phys-20201203
 
BLS署名の実装とその応用
BLS署名の実装とその応用BLS署名の実装とその応用
BLS署名の実装とその応用
 
LazyFP vulnerabilityの紹介
LazyFP vulnerabilityの紹介LazyFP vulnerabilityの紹介
LazyFP vulnerabilityの紹介
 

Recently uploaded

業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成Hiroshi Tomioka
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineerYuki Kikuchi
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?akihisamiyanaga1
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)Hiroki Ichikura
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfFumieNakayama
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfFumieNakayama
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)UEHARA, Tetsutaro
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...博三 太田
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案sugiuralab
 

Recently uploaded (9)

業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
 

C/C++プログラマのための開発ツール

  • 2. • (主にLinux上における)プログラム開発、 デバッグ、不具合調査のためのツールの紹介 • 広く浅く • 同じことを複数の手段で • キーワードや「できること」を知っていれば後は自分で 概要と目的 2/30
  • 3. • gcc, clang • ソース読み • ag, GNU GLOBAL, Doxygen, callgrind • デバッグ • gdb, objdump, c++filt, core dump, addr2line • メモリチェック • ASan, Valgrind, TCMalloc • 静的解析 • cppcheck, scan-build • 実行時解析 • SystemTap, perf 目次 3/30
  • 4. • 警告系オプション • -Wall -Wextra ; 必須 • コンパイラの警告を無視してはいけない • https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect- Options.html • -Wnon-virtual-dtor • -Woverloaded-virtual ; virtualを同名の関数で隠してしまった • 他に-Weffc++など変わりものも • clangには全ての警告を表示する-Weverythingがある • ときどき便利 • -pedantic ; C/C++標準でないGNU拡張を使っていないか C/C++コンパイル時のオプション(1/2) 4/30
  • 5. • 最適化オプション • -Ofast ; 最適化最大 • -march=native ; コンパイル環境のCPUに合わせた最適化 • -DNDEBUG ; assert()マクロの無効化 • デバッグ用オプション • -g ; シンボル情報がつく(速度に影響はない) • -g3 ; マクロも見えるようになる • -S ; アセンブリ出力(生成コードが意図通りか?) • objdumpによる逆アセンブルも便利 • objdump -CSlw -M intel • -C ; C++の関数名を見やすくする(demangle) • -S ; ソースコードを併記 C/C++コンパイル時のオプション(2/2) 5/30
  • 6. • <vector>のソースを見たいが場所はどこ? • echo "#include <vector>"|gcc -x c++ -E -|lv • プロファイルをとる • -pgオプション • ただし関数に介入するのでオーバーヘッドあり • perfやVTune(後述)など別のものがおすすめ その他 6/30
  • 7. • GNU GLOBAL • https://www.gnu.org/software/global/ • 関数が定義されている場所を行ったり来たりできる • 使い方 • 見たいソースのトップディレクトリでgtags • 各自のエディタに応じて設定すること • あとはがんばって:-) • ag • 高速なgrep ; grep -Irw 単語 ./ • apt install silversearcher-ag • highway(https://github.com/tkengo/highway)というのも • Visual Studioなどの統合環境 一度は触ってみるとよい ソースコード読み補助ツール 7/30
  • 8. • ソースコードのドキュメント自動化ツール • apt install doxygen • ソースコードのコメントに書くとマニュアルを生成する • doxygen -gで設定ファイルを作成 • doxygen Doxyfileでhtmlを作成 • コメントのつけ方 • http://www.doxygen.jp/docblocks.html Doxygen 8/30
  • 9. • Graphviz • ものの依存関係を画像表示する • apt install graphviz • 関数の呼び出し関係の画像化 • DoxygenのDoxyfileでHAVE_DOT = yes • callgrind • 呼び出し回数などを可視化 • apt install kcachegrind • Valgrind(後述)の一部 • valgrind –tool=callgrind <binary> • kcachegrind callgrind.out.* 関数呼び出しの可視化 9/30
  • 10. • 落ちるプログラムをデバッグする • rで実行して落ちたところでbtでバックトレースをみる gdb(デバッグツール) #include <stdio.h> #include <stdlib.h> #include <memory.h> int main(int argc, char *argv[]) { char buf[32]; int n = argc == 1 ? 10 : atoi(argv[1]); printf("n=%d¥n", n); memset(buf, 'A', n); printf("n=%d¥n", n); printf("buf[%d-1]=%c¥n", n, buf[n - 1]); } gcc -g t.cpp gdb --args ./aout 10000 r ... Program received signal SIGSEGV, Segmentation fault. 10/30
  • 11. • s ; ステップ実行(1行ずつ実行する) • 最適化オプションありではコードの位置がずれることが多い • 一度コマンドを実行したあと[return]で同じコマンドを実行 • fin ; 関数の中から外に出るまで一気に動く • n ; 関数の中に入らないでステップ実行 • up/down スタックフレームを登ったり降りたり • p 変数 ; 変数を表示する gdbのコマンドいくつか 11/30
  • 12. • gdbを使わず落ちる場所だけ調べる • 落ちたときのレジスタ, ip, backtrace, メモリマップなど表示 libSegFault.so env LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so ¥ SEGFAULT_SIGNALS=all ./a.out 10000 *** Segmentation fault Register dump: RAX: 00007ffeb2670fd0 RBX: 0000000000000000 RCX: 00007ffeb2671000 ... Backtrace: /lib/x86_64-linux-gnu/libc.so.6(memset+0x5d)[0x7f4cf774050d] ./a.out[0x400699] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5)[0x7f4cf76d5f45] ./a.out[0x400569] 12/30
  • 13. • 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
  • 15. • プログラムが異常終了したときの情報を保存したもの • /proc/sys/kernel/core_patternで保存ファイル名を指定 • 例 : カレントディレクトリにcore.<プロセス名> • shellでcoreサイズを制限していないか確認 • bashならulimit -a ; tcshならlimit • 0ならcoreファイルは作られないので設定する • ulimit -c unlimited / limit coredumpsize unlimited • SEGVする実行ファイルを実行する • gdb –c <coreファイル> ./a.outでいつものように操作 core dump sudo sh -c 'echo core.%p > /proc/sys/kernel/core_pattern' 15/30
  • 16. • coreファイルが無かったとき最低限の情報 • ip ; SEGVしたときに実行していたコードのアドレス • libc-2.19.soのip番目をさがす • 00007f55ac1c650d - 7f55ac13a000 = 0x8c50d • libcの0x8c50d番目は何の関数か • addr2lineを使う • memsetのようだ ; 引数がおかしい?(と推測) • objdump -Sでもわかる dmesg [609339.455455] a.out[1088]: segfault at 7fffa910f130 ip 00007f55ac1c650d sp 00007fffa910ca08 error 6 in libc-2.19.so[7f55ac13a000+1ba000] % addr2line -e /lib/x86_64-linux-gnu/libc-2.19.so 0x8c50d /build/eglibc-oGUzwX/eglibc-2.19/string/../sysdeps/x86_64/memset.S:80 16/30
  • 17. • Address Sanitizer(ASan) • メモリ関係のエラーのチェック • バッファオーバーフロー • ヒープオーバーフロー • スタックバッファーオーバーフロー • メモリリーク • -fsanitize=addressをつけてコンパイル メモリ関係 17/30
  • 18. • ./a.out 32 ; 問題なしだが33を指定すると 実行してみる % ./a.out 33 n=33 ==11277==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffdad25b7a0 at pc 0x0000004a691f bp 0x7ffdad25b650 sp 0x7ffdad25ae08 WRITE of size 33 at 0x7ffdad25b7a0 thread T0 #0 0x4a691e in __asan_memset ... This frame has 5 object(s): [32, 36) '' [48, 52) '' [64, 72) '' [96, 128) 'buf' [160, 164) 'n' <== Memory access at offset 128 partially underflows this variable SUMMARY: AddressSanitizer: stack-buffer-overflow ??:0 __asan_memset Shadow bytes around the buggy address: 0x100035a436a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100035a436b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100035a436c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100035a436d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x100035a436e0: 00 00 00 00 f1 f1 f1 f1 04 f2 04 f2 00 f2 f2 f2 =>0x100035a436f0: 00 00 00 00[f2]f2 f2 f2 04 f3 f3 f3 00 00 00 00 ... 18/30
  • 19. • deleteしていない メモリ解放し忘れ % cat t.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
  • 24. • Linux kernelの中身を調べるツール • https://wiki.ubuntu.com/Kernel/Systemtap • インストール • sudo apt install systemtap • シンボル付きのカーネルが必要 • バイナリのインストール方法 • https://wiki.ubuntu.com/Kernel/Systemtap#Where_to_get_de bug_symbols_for_kernel_X.3F • 自分でビルド • https://wiki.ubuntu.com/Kernel/Systemtap#How_do_I_build_a _debuginfo_kernel_if_one_isn.27t_available.3F • sudo dpkg -i linux-*.ddeb linux-*.debのあとリブート SystemTap 24/30
  • 25. • kernel内の関数の場所を調べる • write(2)を調べたい • 内部的にはSyS_write • fs/read_write.cの514行目にある • sync(8)したときの流れをみたい • ext4のwriteまわりの関数は何があるだろう • なんとなくext4_writepagesを見てみる 使い方 % stap -l 'kernel.function("SyS_write")' kernel.function("SyS_write@/*/fs/read_write.c:514") % stap -l 'kernel.function("ext4_write*")' kernel.function("ext4_write_begin@/*/fs/ext4/inode.c:958") kernel.function("ext4_write_dquot@/*/fs/ext4/super.c:5032") ... kernel.function("ext4_writepage_trans_blocks@/*/fs/ext4/inode.c:4888") kernel.function("ext4_writepages@/*/fs/ext4/inode.c:2473") 25/30
  • 26. • awkライクなスクリプト言語 • コンパイルして実行できる • 裏でkernel moduleになってloadされる • ext4_writepagesが呼ばれたときにpidが自分が指定したコマ ンドなら関数名と引数とバックトレースを表示する • .call ; 呼ばれたとき • pid() ; 今のpid • $$parms ; 引数 stapスクリプト >cat a.stp probe kernel.function("ext4_writepages").call { if (pid() != target()) exit() printf("%s(%s)¥n", probefunc(), $$parms) print_backtrace() } 26/30
  • 27. • -c <command>でコマンド実行 • いろいろ試してみる syncコマンドを実行してみる % sudo stap a.stp -c "sync" ext4_writepages(mapping=0xffff880402e009b0 wbc=0xffff880405a9bc58) 0xffffffff81247f80 : ext4_writepages+0x0/0xdb0 [kernel] 0xffffffff8115e47e : do_writepages+0x1e/0x40 [kernel] 0xffffffff811eaae0 : __writeback_single_inode+0x40/0x2a0 [kernel] 0xffffffff811eb9ca : writeback_sb_inodes+0x26a/0x440 [kernel] 0xffffffff811ebc3f : __writeback_inodes_wb+0x9f/0xd0 [kernel] 0xffffffff811ebef3 : wb_writeback+0x283/0x320 [kernel] 0xffffffff811ed77c : bdi_writeback_workfn+0x11c/0x4a0 [kernel] 0xffffffff81086078 : process_one_work+0x178/0x470 [kernel] 0xffffffff81086e91 : worker_thread+0x121/0x410 [kernel] 0xffffffff8108dc79 : kthread+0xc9/0xe0 [kernel] 0xffffffff8173a3e8 : ret_from_fork+0x58/0x90 [kernel] 27/30
  • 28. • g++ user-backtrace.cpp -g • sudo stap user.stp –c “./a.out” | c++filt • print_ubacktrace でバックトレース ユーザランドのバックトレース probe process("./a.out").function("*").call { printf("%s -> %s¥n", thread_indent(1), probefunc()) } probe process("./a.out").function("*").return { printf("%s <- %s¥n", thread_indent(-1), probefunc()) } 0 a.out(23897): -> main 10 a.out(23897): -> h(int) 26 a.out(23897): -> g(int) 30 a.out(23897): -> f(int) 40 a.out(23897): <- g(int) 42 a.out(23897): -> f(int) 45 a.out(23897): <- g(int) 47 a.out(23897): <- h(int) 48 a.out(23897): -> g(int) 51 a.out(23897): -> f(int) 54 a.out(23897): <- g(int) 56 a.out(23897): -> f(int) 59 a.out(23897): <- g(int) 60 a.out(23897): <- h(int) 62 a.out(23897): <- main 64 a.out(23897): <- 0x7fb394b0cf45 #include <stdio.h> void f(int x) { printf("f=%d¥n", x); } void g(int x) { puts("g"); for (int i = 0; i < 2; i++) { f(x + i); } } void h(int x) { puts("h"); for (int i = 0; i < 2; i++) { g((x + i) * (x + i)); } } int main(int argc, char *[]) { h(argc); } 28/30
  • 29. • SystemTap Beginners Guide • https://sourceware.org/systemtap/SystemTap_Beginners_Guide/ • スクリプトの文法 • https://sourceware.org/systemtap/langref/Language_elements.html • サンプルいろいろ • https://sourceware.org/systemtap/examples/ • 関数いろいろ • https://sourceware.org/systemtap/man/ • 例 addrからn個のデータを文字列化 kernel_string_n(addr, n) • Ftraceというkernelのevent記録ツールもある • cf. ファイルキャッシュクリアの謎 • http://www.slideshare.net/herumi/kernel-fcachebug 参考文献 29/30
  • 30. • CPU内部のカウンタを使って詳細な情報を収集 • apt install linux-tools-common • perf listで取得可能な一覧を表示 • VM上では取得可能なeventは極めて制限される • perf stat -e <イベント> <実行ファイル> • sudo perf top ; 現在のkernelの詳細なtopを表示 • IntelのVTuneはこれのGUI版(便利) perf List of pre-defined events (to be used in -e): cpu-cycles OR cycles [Hardware event] instructions [Hardware event] cache-references [Hardware event] cache-misses [Hardware event] branch-instructions OR branches [Hardware event] ... 30/30