次: , 前: Stack, 上: Stack


6.1 スタック・フレーム

呼び出しスタックは、 スタック・フレーム、 または短縮してフレームと呼ばれる、 連続した小部分に分割されます。 個々のフレームは、 ある関数に対する1回の呼び出しに関連するデータです。 フレームには、 関数への引数、 関数のローカル変数、 関数の実行アドレスなどの情報が含まれます。

ユーザ・プログラムが起動されたとき、 スタックにはmain関数のフレームが1つ存在するだけです。 これは、 初期フレームまたは「最上位のフレーム」と呼ばれます。 関数が呼び出されるたびに、 新たにフレームが作成されます。 関数が復帰すると、 その関数を呼び出したときに生成されたフレームが取り除かれます。 関数が再帰的に呼び出される場合、 1つの関数に対して多くのフレームが生成されるということもありえます。 実際に実行中の関数に対応するフレームは、 「最下位のフレーム」と呼ばれます。 これは、 存在するすべてのスタック・フレームの中で、 最も新しく作成されたものです。

ユーザ・プログラムの内部においては、 スタック・フレームはアドレスによって識別されます。 スタック・フレームは多くのバイトから構成され、 それぞれがそれ自身のアドレスを持っています。 そのアドレスがフレームのアドレスとなるような1バイトを選択する慣習的な方法を、 すべての種類のコンピュータが提供しています。 通常、 あるフレーム内部で実行中は、 そのフレームのアドレスがフレーム・ポインタ・レジスタと呼ばれるレジスタに格納されています。

GDBは、 既存のスタック・フレームのすべてに番号を割り当てます。 最下位のフレームは0で、 それを呼び出したフレームは1となります。 以下、 最下位のフレームを起点として、 順番に値を割り当てていきます。 これらの番号はユーザ・プログラム内部には実際には存在しません。 これらの番号は、 GDBコマンドでスタック・フレームを指定することができるように、 GDBによって割り当てられたものです。

コンパイラによっては、 スタック・フレームを使用しなくても実行可能なように関数をコンパイルする方法を提供しているものもあります (例えば、 gccのオプション`-fomit-frame-pointer'を指定すると、 フレームを持たない関数が生成されます)。 これは、 フレームをセットアップする時間を節約するために、 頻繁に利用されるライブラリ関数に対してしばしば適用されます。 これらの関数の呼び出しを処理するためにGDBが提供する機能は限られています。 最下位のフレームの関数呼び出しがスタック・フレームを持たない場合、 GDBは、 あたかもそれが通常どおりに番号0のフレームを持つものとみなして、 関数呼び出しの連鎖を跡づけることができるようにします。 しかしながら、 最下位以外のスタック位置に存在する、 フレームを持たない関数に対しては、 GDBは特別な処置を取りません。

frame args
frameコマンドによって、 あるスタック・フレームから別のスタック・フレームに移動し、 選択したスタック・フレームを表示させることができます。 argsは、 フレームのアドレスまたはスタック・フレーム番号です。 引数なしで実行すると、 frameコマンドはカレントなスタック・フレームを表示します。


select-frame
select-frameコマンドによって、 フレームを表示することなく、 あるスタック・フレームから別のスタック・フレームに移動することができます。 これは、 frameコマンドから、 表示処理を取り除いたものです。