デバッガの使い方
#05/04/2001最終変更
#04/25/2001新規作成


1 ソースを ダウンロード し、filein して下さい。

  インストールがうまく出来たか、チェックします。

  Workspace で、 DebugDemo go と入力し、do it( alt -d )として下さい。
  Halt と タイトルバーに表示された、ノーティファイヤ画面が出ます。「Proceed」ボタンを3回押して、
  先に進んでください。Transcript に ’g ->300' と表示されれば成功です。
  DebugDemo go2 も実行してみてください。今度は、「Proceed」ボタンは1回押すだけです。

  ソースは、カテゴリ Demo の クラス DebugDemo です。

          



2 ソースの説明

   DebugDemo class>>go クラスメソッド
     | a |
     ClassCalc := 555.
     a := self new calc: 10.
     Transcript show: 'G ->', a printString; cr.
  
   DebugDemo class>>go2
     | a |
     ClassCalc := 555.
     a := self new calc2: 10.
     Transcript show: 'G2->', a printString; cr.

   DebugDemo>>calc: aNumber
      "calc" 
      | tempa |
 
      tempa := aNumber * aNumber.  10×10 ->100
      self halt.
      forCalc1 := tempa + tempa.          ->200
      self halt.
      forCalc2 := forCalc1 + tempa.       ->300
      self halt.
      ^forCalc2

   DebugDemo>>calc2: aNumber
      "calc2"  
     | tempa |

     tempa := 1.
     self halt: 'first'.
     tempa := self subCalc: aNumber.   -> 10000 メソッドの呼び出しの入れ子
     forCalc1 := tempa + tempa.        -> 20000
     forCalc2 := forCalc1 + tempa.     -> 30000
     ^forCalc2

3 Debugger の概要(Proceed, Restart, Step)

  Workspace にて DebugDemo go で実行して下さい。

  次のような、デバッガーのノーティファイヤー(告知画面)が開きます。

  

  ここで、 Proceed : エラーを無視して先に進む  Abandon : 実行を中止して、ウィンドウを閉じる です。
   Debug を選択します。一番上のペインで、DebugDemo>>calc:  の行を選択すると、次のような表示になります。

  

  calc: aNumber インスタンスメソッドの self halt. 行で停止していることが判ります。これは、デバッグ用の強制停止で、 breakpoint です。
  下の4つのペインはインスペクタが2つです。左から、インスタンス変数、その値、一時変数(含む引数)、その値となります。

 tempa := aNumber * aNumber. の行が実行され、引数 aNumber (10)の2乗が tempa にセットされている はずです。
  順番に値を見て行くと、
  

  self -> a DebugDemo
    all inst vars -> forCalc1: nil forCalc2: nil
    forCalc1 -> nil
    forCalc2 -> nil 

    thisContext -> DebugDemo>>calc:
    aNumber -> 10
    tempa -> 100

ボタンの Proceed を押して下さい。ノーティファイヤの Debugボタン -> calc で次のような表示になります。

  

  次の breakpoint である、2行下の self halt. 行で停止していることが解ります。
    forCalc1 := tempa + tempa. が実行され、forCalc1 が200になっています。
    Proceed は、実行を継続します。

  再度、 Proceed を押して下さい。ノーティファイヤの Debugボタン -> calc次のような表示になります。

  

  最後のブレークポイントで止まっています。

  今度は、 Restart を押して見ましょう。
  最初の Proceed と同じ画面になります。 Restart は実行状態をクリアして、最初から実行することが解り
    ます。


    次は、Step です。
    Debugger の中央のソースペインで、2番目と3番目の self halt を削除してください。
    ついでに、最初の self halt を self halt:'first' に変えてください。
    Restart すると、デバッガのタイトルバーに、'Halt: first' と説明が出ているはずです。
    Step ボタンを押して下さい。ソースのカーソルが動き、一行ずつ実行されていることが解ります。

4 Debugger の概要(Send)

   ここで、 Send を押してください。subCalcメソッドの中にはいります。さらに step を押し、
   Send を押せば、下図のように subusubCalc メソッドが表示されます。この時、一時変数は、移動後の
   メソッドの値を表示しています。

   
 
  ソースコードの変更を先程おこないましたが、インスペクタでオブジェクトの値の変更も可能です。
  >>calc2: のメソッド呼び出しから戻ったところで、tempa の 値を 10000 -> 500000 に変更してみま
  しょう。step の実行結果は、 forCalc2 -> 520000 となります。

  
  


5 まとめ

     スタックペイン: 
          プログラムの停止時のメソッドが一番上にあり、その下は、呼び出し元のメソッドのスタック
     (呼びだした逆の順に上から表示される)。
          表示は、 レシーバのクラス >> メッセージセレクタ と成っている。
          どの行からでも、デバッグを開始できる。
  
      ソースペイン :
          スタックペインで選択された行のソースを表示する。ソースを変更しながら、デバッグが出来る。
    
     ボタン
    Proceed  : エラーを無視して先に進む。halt などと組み合わせ、任意のbreakpoint まで進む。
    Restart  : 初期化し、最初から実行。
       send      : 最少範囲の評価。呼び出し先のセレクタ(メソッド)があれば、その内部に移動して実行。
       step      : メッセージのワンステップずつ実行(1セレクタ毎)
    browser  : 現在のソースの行を、system browser で表示

     インスペクタ
        左 : インスタンス変数
        右 : 引数を含む一時変数

      print it , inspect などのコマンドは、各ペインで有効。

6 エラー時のデバッグ。

  上記では、self halt. でブレークポイントを挿入することで強制停止させ、ステップ実行でデバッグして
    いる。この手法は、クラスライブラリを調べる時にも有効。
    また、コードをデバッガ上で書くというのも有効なテクニックだそうだ。

    一方、大半のエラーは、"Message not understood: xxxx" になる。これは、レシーバ xxxx に対する
    メッセージが理解されなかったことを示す。つまり、手続きの呼びだし失敗である。

  この場合、エラー停止行から前に遡って、呼びだし関係を確認し、引数などの型を確認することで、エラーを
    分析し、バグを発見できる。

  (以上)