Oracle® Solaris Studio 12.4: dbxtool チュートリアル

印刷ビューの終了

更新: 2014 年 10 月
 
 

ウォッチポイントとステップ動作の使用法

これで Interp::dispatch() にブレークポイントが 1 つできたので、「デバッガ・コンソール」ウィンドウで「再起動」 image:「再起動」ボタン を再度クリックして Return キーを押すと、実行可能コードを含む dispatch() 関数の最初の行でプログラムが停止します。

image:122 行目で実行が停止した「エディタ」ウィンドウ

    find() に渡される argv[0] の問題が特定されたので、argv に対してウォッチポイントを使用します。

  1. 「エディタ」ウィンドウで argv のインスタンスを選択します。

  2. 右クリックして「新規ウォッチポイント」を選択します。選択したテキストを含む「新規ウォッチ」ダイアログボックスが表示されます。

    image:「新規ウォッチポイント 」ダイアログボックス
  3. 「OK」をクリックします。

  4. 「ウォッチ」ウィンドウを開くには、「ウィンドウ」->「ウォッチ」(Alt+Shift+2) を選択します。

  5. 「ウォッチ」ウィンドウで、argv を展開します。

    image:argv が展開された「ウォッチポイント 」ウィンドウ

    argv は初期化されておらず、argv はローカル変数であるため、前の呼び出しでスタックに残されたランダムな値を「継承」している可能性があることに注意してください。これは問題の原因でしょうか。

  6. 緑色の PC の矢印が int argc = 0; を指すまで、「ステップ・オーバー」(F8) image:「ステップオーバー」ボタン を 2 回クリックします。

  7. argcargv のインデックスになるため、argc のウォッチポイントも作成します。argc も現時点では初期化されておらず、意図しない値が含まれている可能性があることに注意してください。

    argc のウォッチポイントは、argv のウォッチポイントのあとで作成したため、「ウォッチ」ウィンドウでは 2 番目に表示されます。

  8. ウォッチポイント名をアルファベット順に並べるには、「名前」列見出しをクリックして列をソートします。次の図のソートの三角印を確認してください。

    image:ウォッチポイントがソートされた「ウォッチポイント」ウィンドウ
  9. 「ステップ・オーバー」(F8) image:「ステップオーバー」ボタン をクリックします。

    argc は、初期化された値である 0 を示し、値がちょうど変更されたことを示す太字で表示されます。

    image:argc 値が太字で表示された「ウォッチポイント 」ウィンドウ

    アプリケーションが strtok() を呼び出します。

  10. 「ステップ・オーバー」をクリックして、関数をステップオーバーし、たとえば、バルーン式を使用して、token が NULL であることを監視します。

    strtok() 関数は、たとえば文字列をいずれかの DELIMITERS で区切られたトークンに分割するのに役立ちます。詳細は、strtok(3) のマニュアルページを参照してください。

  11. 「ステップ・オーバー」を再度クリックして、トークンを argv に割り当てます。次に、ループ内で strtok() の呼び出しが行われます。

    ステップオーバーすると、ループには入らずに (これ以上トークンがないため)、代わりに NULL が割り当てられます。

  12. サンプルプログラムがどこでクラッシュしたかを特定するため、その割り当てもステップオーバーすると呼び出しのしきい値に達します。

  13. プログラムがこの時点でクラッシュすることをダブルチェックするため、find() の呼び出しをステップオーバーします。

    「シグナルがキャッチされました」警告ボックスが再度表示されます。

    image:「シグナル捕獲 」警告ボックス
  14. 以前のように「破棄して一時停止 」をクリックします。

    Interp::dispatch() で停止したあとの find() の最初の呼び出しが、本当に不具合のある場所です。

    最初に find() を呼び出した場所にすばやく戻ることができます。

    1. 「呼び出し元を現在に設定」 image:「呼び出し元を現在に設定」ボタン をクリックします。

    2. find() の呼び出しサイトで行ブレークポイントを切り替えます。

    3. 「ブレークポイント」ウィンドウを開いて、Interp::dispatch() 関数ブレークポイントを無効にします。

      dbxtool の表示は次の図のようになります。

      image:1 つを無効にし、2 つのブレークポイントを示す「エディタ 」ウィンドウ
    4. 下矢印は、2 つブレークポイントが 141 行に設定され、それらの 1 つが無効であることを示しています。

  15. 「デバッガ・コンソール」ウィンドウで「再起動」 image:「実行」ボタン をクリックし、Return キーを押します。

    プログラムが find() の呼び出しの前に戻ります。「再起動」ボタンは再起動を実行します。デバッグ中は、初期の起動より再起動の方が頻繁に行われます。


    ヒント  -  たとえば、プログラムを再構築する場合、バグを検出して修正したあとで、dbxtool を終了して、再起動する必要はありません。「再起動」ボタンをクリックすると、dbx はプログラム (またはその構成要素) が再コンパイルされていることを検出し、再ロードします。 したがって、デバッグ中の問題に対してすぐに使用できるように、dbxtool をデスクトップ上に、通常は最小化して保持することを検討してください。
  16. バグはどこにあるでしょうか。ふたたびウォッチポイントをみてみましょう。

    image:「ウォッチポイント」ウィンドウ

    行が空であり、トークンを持っていなかったため、strtok() の最初の呼び出しが NULL を返したため、argv[0] が NULL であることに注意してください。

    必要に応じて、このチュートリアルの残りに進む前にこのバグを修正してください。

    デバッガでプログラムを実行する場合は、ブレークポイントスクリプトを使用してコードにパッチを適用するの説明に従って、デバッガでコードにパッチを適用できます。

コード例の開発者は、この条件に対しておそらくテストし、Interp::dispatch() の残りを省略しているはずです。