あなたのプログラムが関数をコールする時、プログラムがどのようにコール されたのかという情報は、スタックフレームと呼ばれるデータの ブロックに保存されます。フレームはまた、コール時の引数と、コール された関数のローカル変数の内容を含んでいます。全てのスタック フレームはコールスタックと呼ばれるメモリ領域に配置されます。
あなたのプログラムが停止した時、GDB のスタック調査用のコマンドを 使うことによって、あなたはこれらの全ての情報を見ることができます。
ある特定のスタックフレームが GDB によって選択された場合、多くの GDB の コマンドは選択されたフレームを無条件に参照します。特に、プログラム 内の変数値を GDB に問い合わせた場合、その値は選択されたフレーム上の ものです。GDB には、あなたの興味あるフレームがどれであるのかを選択する ための特別なコマンドがあります。
プログラムが停止した時、GDB はカレントで実行されているフレームを 自動的に選択します。フレームは `frame' コマンドによって簡単に指定 することができます(“6.4 フレーム上の情報”をご覧下さい)。
あなたのプログラムがスタートした時、スタックは関数 main
に関する
たった一つのフレームしかありません。これは初期のフレーム、
又は一番外のフレームと
呼ばれます。関数がコールされる度に、新しいフレームが生成されます。
関数がリターンする度に、その関数が作り出したフレームは削除されます。
関数がリカーシブな場合、同一関数に対するフレームが多数生成されます。
関数のフレームにおいて処理の実行が実際に行われるのは、最深部の
フレームと呼ばれるものです。これは、存在する全てのスタックフレームの
中で一番最近に生成されたものです。
あなたのプログラムの中で、スタックフレームはアドレスによって識別 されます。スタックフレームは自分自身のアドレスも持った多くのバイト列を 含んでおり; 様々な種類のコンピュータにおいて、フレームのアドレスを持ったバイト列の 一つを選ぶという選択上の決まりがあります。通常、このアドレスは、 フレーム内で処理が実行している時、フレームポインタ・レジスタと 呼ばれるレジスタに保持されています。
GDB は、存在する全てのスタックフレームに、コールされた最深部の フレームをゼロとしてスタートした番号を、上に向かって順次割り当てて います。これらの番号はあなたのプログラムの中に実際に存在するわけでは ありません; これは、GDB のコマンドに対してスタックフレームを指示する方法として 与えられたものです。
多くの GDB のコマンドは、一つのスタックフレームを無条件に参照します。 GDB は、選択されたスタックフレームと呼ばれるスタックフレームを記録 しており; あなたは任意のフレームをワンセットの GDB コマンドを使って選択することが でき、そこで、他のコマンドは新しいフレームを処理するようになります。 あなたのプログラムが停止した場合、GDB は最深部のフレームを自動的に 選択します。
ある関数はスタック上にフレームを確保しないで動作するようにコンパイル されているかもしれません。このようなケースは、非常に多用される ライブラリ関数のスタック生成時間を省略するような場合、時々おこります。 GDB は、このような関数起動の振るまいに対する便宜を制限します; もし、最深部の関数がスタックフレームなしで起動されたら、GDB は0への 仮想スタックフレームを与え、関数コールのチェインが正しくトレース できるようにします。最深部の関数がフレームを持たない場合、 スタック上の結果は未定義となります。
あなたは、通常 Control-C に設定されているシステム割り込み文字を 入力することによって、いつでもバックトレースを停止させることができます。
バックトレースが表示する各々の行には、フレーム番号、関数名、そして プログラムカウンタ値が表示されます。
もし、ソースファイルと共に関数のシンボルテーブル・データがフルに 読み込まれたような状況にあれば、バックトレースはソースファイル名と 行番号、そして関数の引数を表示します。(プログラムカウンタ値は、行番号を 持つコードの先頭の場合、省略されます。)
もし、ソースファイルのシンボルデータがフルに読み込まれた状態でない 場合は、スキャンのみ実行され、この拡張情報は省略符号 (...) に置き換え られます。あなたはまた、フレームを選択することで、フレームに関する ソースファイル上のシンボルデータを強制的に読み込ませることができます (“6.3 フレームの選択”を参照して下さい)。
ここにバックトレースの例を示します。これは、`bt 3' というコマンドに よって生成されたもので、最深部から3つのフレームを表示しています。
#0 rtx_equal_p (x=(rtx) 0x8e58c, y=(rtx) 0x1086c4) (/gp/rms/cc/rtlanal.c line 337) #1 0x246b0 in expand_call (...) (...) #2 0x21cfc in expand_expr (...) (...) (More stack frames follow...)
expand_call
と expand_expr
という関数は、シンボルの詳細に
関するファイルがまだ読み込まれていないものです。全ての詳細は、
rtx_equal_p
という関数上に表れており、それは `rtlanal.c'
と
いうファイルの中に含まれています。この関数の引数である x
と
y
は、その値が表示されています。
main
関数のフレームです。
#3 main (argc=3, argv=??, env=??) at main.c, line 67 67 read_input_file (argv[i]);