これで Interp::dispatch() にブレークポイントが 1 つできたので、「デバッガ・コンソール」ウィンドウで「再起動」 を再度クリックして Return キーを押すと、実行可能コードを含む dispatch() 関数の最初の行でプログラムが停止します。
find() に渡される argv[0] の問題が特定されたので、argv に対してウォッチポイントを使用します。
「エディタ」ウィンドウで argv のインスタンスを選択します。
右クリックして「新規ウォッチポイント」を選択します。選択したテキストを含む「新規ウォッチ」ダイアログボックスが表示されます。
「OK」をクリックします。
「ウォッチ」ウィンドウを開くには、「ウィンドウ」->「ウォッチ」(Alt+Shift+2) を選択します。
「ウォッチ」ウィンドウで、argv を展開します。
argv は初期化されておらず、argv はローカル変数であるため、前の呼び出しでスタックに残されたランダムな値を「継承」している可能性があることに注意してください。これは問題の原因でしょうか。
緑色の PC の矢印が int argc = 0; を指すまで、「ステップ・オーバー」(F8) を 2 回クリックします。
argc は argv のインデックスになるため、argc のウォッチポイントも作成します。argc も現時点では初期化されておらず、意図しない値が含まれている可能性があることに注意してください。
argc のウォッチポイントは、argv のウォッチポイントのあとで作成したため、「ウォッチ」ウィンドウでは 2 番目に表示されます。
ウォッチポイント名をアルファベット順に並べるには、「名前」列見出しをクリックして列をソートします。次の図のソートの三角印を確認してください。
「ステップ・オーバー」(F8) をクリックします。
argc は、初期化された値である 0 を示し、値がちょうど変更されたことを示す太字で表示されます。
アプリケーションが strtok() を呼び出します。
「ステップ・オーバー」をクリックして、関数をステップオーバーし、たとえば、バルーン式を使用して、token が NULL であることを監視します。
strtok() 関数は、たとえば文字列をいずれかの DELIMITERS で区切られたトークンに分割するのに役立ちます。詳細は、strtok(3) のマニュアルページを参照してください。
「ステップ・オーバー」を再度クリックして、トークンを argv に割り当てます。次に、ループ内で strtok() の呼び出しが行われます。
ステップオーバーすると、ループには入らずに (これ以上トークンがないため)、代わりに NULL が割り当てられます。
サンプルプログラムがどこでクラッシュしたかを特定するため、その割り当てもステップオーバーすると呼び出しのしきい値に達します。
プログラムがこの時点でクラッシュすることをダブルチェックするため、find() の呼び出しをステップオーバーします。
「シグナルがキャッチされました」警告ボックスが再度表示されます。
以前のように「破棄して一時停止 」をクリックします。
Interp::dispatch() で停止したあとの find() の最初の呼び出しが、本当に不具合のある場所です。
最初に find() を呼び出した場所にすばやく戻ることができます。
「呼び出し元を現在に設定」 をクリックします。
find() の呼び出しサイトで行ブレークポイントを切り替えます。
「ブレークポイント」ウィンドウを開いて、Interp::dispatch() 関数ブレークポイントを無効にします。
dbxtool の表示は次の図のようになります。
下矢印は、2 つブレークポイントが 141 行に設定され、それらの 1 つが無効であることを示しています。
「デバッガ・コンソール」ウィンドウで「再起動」 をクリックし、Return キーを押します。
プログラムが find() の呼び出しの前に戻ります。「再起動」ボタンは再起動を実行します。デバッグ中は、初期の起動より再起動の方が頻繁に行われます。
バグはどこにあるでしょうか。ふたたびウォッチポイントをみてみましょう。
行が空であり、トークンを持っていなかったため、strtok() の最初の呼び出しが NULL を返したため、argv[0] が NULL であることに注意してください。
必要に応じて、このチュートリアルの残りに進む前にこのバグを修正してください。
デバッガでプログラムを実行する場合は、ブレークポイントスクリプトを使用してコードにパッチを適用するの説明に従って、デバッガでコードにパッチを適用できます。
コード例の開発者は、この条件に対しておそらくテストし、Interp::dispatch() の残りを省略しているはずです。