view software/gdb/how_to/43B8C054697073.md @ 131:d585ad848911

backup 2023-07-11
author autobackup
date Tue, 11 Jul 2023 00:10:03 +0900
parents e12992dca4a0
children
line wrap: on
line source

# デバッグの手法
私が使っているデバッグの手法を紹介します。

## gdbを使ってみる
### gdbの紹介

gdbは The GNU Debuggerです。C言プログラムをgdbの上で走らせ、
特定の箇所で止めて周辺の値を調べたり、プログラムがどの辺りで止まったかを詳しくレポートさせたりします。

MacやLinuxには元から入っていますので、何もインストールする必要はありません。
難しく考えるかもしれませんが、要はプログラムを好きな場所で止めたり、
値を好きなように変更してみたり、もしくはプログラムの変数の中身を出力してみたりするだけです。

ただこれだけでも立派なデバッグ作業なのです。
使い慣れるとgdb無しではプログラムしたくなくなります。

### gdbを使う前に

gdbを使うには、実行ファイルにgdbに必要なデバッグ情報を付加してあげる必要があります。
デバッグ情報を付加するにはccに-gオプションを付けます。
では実際に試してみます。&ref(hello_gdb.c);
を適当なディレクトリに保存してコンパイルします。

```
 cc hello_gdb.c -g
```

  -gオプションでコンパイルするといつものようにa.outが出力されます。
下準備はこれで終わりですが、a.outを実行するとエラーがでます。

 セグメントエラー

...これはなんでしょう?


### gdbでよく使うコマンド

- プログラムの実行

プログラムを実行するには run コマンドを使います。プログラムに引数 `<option>` があれば後に付けることができます。

```
 (gdb) run <option>
```

プログラムを(breakなどを用いて)一時停止し、再開するときには continue を使います。

```
 (gdb) continue
```

一時停止したプログラムを一行だけ実行することもできます。step と next の二つがありますが、step は関数を呼び出すときにその関数内も一行づつ実行し、next は関数内には入りません。

```
 (gdb) step
 (gdb) next
```

- ブレークポイント

プログラムを一時停止したい場合はブレークポイントを設けます。関数 `<function_name>` にブレークポイントを設けるには以下のように break コマンドを使います。関数 `<function_name>` が呼ばれると `<function_name>` の最初の行でプログラムが一時停止します。また、ファイル名`<file>` を指定したい場合は `<file>`:`<function_name>` のようにコロンを挟んで指定します。

```
 (gdb) break <function_name>
 (gdb) break <file>:<function_name>
```

プログラム中の全関数を見たい場合は以下のコマンドを実行します。

```
 (gdb) info functions
```

関数名ではなく、行番号 `<line_num>` を指定することもできます。方法は関数名と同じです。

```
 (gdb) break <line_num>
 (gdb) break <file>:<line_num>
```

ブレークポイントの一覧が見たい場合は以下のコマンドを使います。

```
 (gdb) info breakpoints
```

ブレークポイントの削除には delete を使います。`<break_number>` は info breakpoints で確認できる、ブレークポイントの番号です。

```
 (gdb) delete <break_number>
```

- 表示

実行中のプログラムの変数を見たい場合は print を使います。
print は変数 `<variable>` やポインタが指す先の値 `*<pointer>`,式 `<expression>`などを表示することができます。

```
 (gdb) print <variable>
 (gdb) print *<pointer>
 (gdb) print <expression>
```

実行しているプログラムのソースコードを表示するには list を使います。引数を与えないと現在実行している行周辺を表示します。関数 `<function>` を与えるとその関数を、行番号 `<line_number>` を与えるとその行番号周辺のソースコードを表示します。

```
 (gdb) list
 (gdb) list <function>
 (gdb) list <line_number>
```

通常は10行づつ表示しますが、以下のように set を用いて `<number>` 行づつ表示できるように変更できます。

```
 (gdb) set listsize <number>
```

- スタック・フレーム

現在実行している関数がどのようにして呼ばれたかを知りたい場合は where か backtrace を使います。

```
 (gdb) where
```

where はスタックに詰まれた関数の層を表示します。この層の一つ一つをフレームといいます。現在プログラムが実行しているフレームを見るには frame を使います。frame に引数として各フレームに割り当てられている番号 `<f_number>` (whereで確認できる)を指定すると、そのフレームへ移動します。

```
 (gdb) frame
 (gdb) frame <f_number>
```

層になっているフレームは up と down を使うことで、上または下方向へ移動できます。引数として数字 `<number>` を与えると `<number>` 個分移動します。

```
 (gdb) up <number>
 (gdb) dowm <number>
```


### 参考文献

本ページは以下のページを参考にしました。より詳しくGDBを知りたい方は一読することをお推めします。

[[Debugging with GDB:http://www.asahi-net.or.jp/  wg5k-ickw/html/online/gdb-5.0/gdb-ja_toc.html]]