メモリ関連エラーの追及, 性能プ ロファイル メモリ関連エラー 空間軸上の間違い • 領域オーバーフロー • Nバイト割り当てて, Nバイト目以降(Nバイト目を含む)を 触る • ポインタの初期化し忘れ, ポインタ変数の破壊 時間軸上の間違い • 早すぎる解放(free) • 解放し忘れ(リーク) 領域オーバーフローの例 char * a = (char *)malloc(N); a[N] = …; char a[N]; a[N] = …; typedef struct foo { … } foo, * foo_t; foo_t = (foo_t)malloc(sizeof(foo_t)); char * s_copy = (char *)malloc(strlen(s)); strcpy(s_copy, s); おきていること mallocした領域の「ちょっと後ろ」に書き込む( 必ず「ちょっと」かどうかはわからないが, 割と 多くの場合「ちょっと」) 典型的症状 そこに何があるかで挙動は千差万別だが… • mallocの場合, malloc自身の管理領域, 別の mallocで割り当てた領域 • 将来のmalloc/free中にsegmentation fault • 別の, mallocした領域を破壊 • 局所配列の場合, 別の変数 • 別の変数を破壊 • それがポインタなら将来そのポインタを通じてメモリを アクセスしたときにsegmentation fault • 「大幅に」はみ出せばアクセス不能領域 • segmentation fault ポインタの初期化し忘れ, 破壊 char * a; a[0] = … foo * a = mk_foo(); … foo * mk_foo() { returnし忘れ; } 症状: (aを通じてメモリをアクセスした際), まっ たくでたらめなアドレスを参照しにいくことにな る(segmentation fault, 変数の破壊) はやすぎる解放 char * a = (char *) malloc(…); free(a); a[0] = … 解放後, その領域が別のmallocによって割り 当てられ, その後aを通じてその領域に書き込 んだ際, その領域を破壊 メモリ関連エラーの厄介な点 間違った際の挙動は「不定」 • 領域はみ出し, 初期化し忘れなどで何が起こるか は, プログラマの知らないmallocやスタックなどの memoryレイアウトで決まる • 症状 • 最適化を外したら「なぜか」動いた • このメモリを1バイト余計に割り当てたら「なぜか」動い た(これで正しい場合もあるが) 間違ってもすぐに症状が現れない • 破壊した領域を使ったときに最終的な症状が現 れる メモリ関連エラーの回避・デバッグ ツール GC • 時間軸方向のエラーをなくす(freeを呼ばなくてよ い) • 空間軸方向のエラーには無力 MALLOC_CHECK_, valgrind • 空間軸方向のエラーの一部を検出 MALLOC_CHECK_ 朗報: 最近のLinuxのdefaultのmallocに組み 込まれている(installの必要なし) 動作: • mallocした領域を「ちょっと」踏み越えたアクセス を検出 • いつ? malloc/free時に検出 環境変数MALLOC_CHECK_によって動作 を変えられる(cf. man malloc) 効果的な使い方 エラーが出るようになったら, -g でコンパイル し, gdbで走らせる エラーがおきるとabort関数を呼び, gdb内で実 行が停止する gdbのupコマンドでエラーが起きた場所を突き 止める 制限 エラーがチェックされるのはmalloc/free時のみ 「領域はみ出しアクセス」を行った瞬間ではない 基本はmallocの管理領域の破壊を検出している だけなので, malloc以外のメモリ領域のはみ出し には無力 mallocに限ってもすべての領域はみ出しが検出 されるわけではなく, 実際カバー率は低い valgrind (Ubuntu) apt-get install valgrind それ以外の場合, Googleで検索 -gでコンパイルしたプログラムを, valgrind <コマンド> で実行するだけ valgrind プログラムをその場で書き換えて実行する( 個々のメモリアクセスを監視)ため, • 「領域はみ出しの瞬間」を検出できる • 検出力(カバー率)が高い 制限: • おそい そのほか 常に最大限の警告を出すオプション(gccであ れば –Wall)をつけてコンパイル 警告を無視しない 性能プロファイル gcc –pg … (コンパイル時とリンク時の両方) ./minipy … (実行) “gmon.out”というファイルが出来る gprof minipy で結果を表示
© Copyright 2024 ExpyDoc