デバッグの準備
- 関数内で
C-u C-M-x M-x edebug-all-defsを実行した上でeval-buffer,eval-region,eval-defunM-x edebug-all-formsを実行した上でeval-buffer,eval-regionを使うと(範囲内にある)定義以外のフォームもデバッグするM-x edebug-eval-top-level-formを使うとポイントがある場所(直後またはフォーム内であればそのトップレベル)のフォームをデバッグする
(参考: Instrumenting)
ストップポイント
(defun fun (a b) .(if .(< a. b.). .(insert .(format "%s %s %s" '(1 2 3) [1 2 3] .`(1 2 ,.(+ a. b.).).).). .(fun b. a.).).)
要するにリストの前後と変数参照の後。リテラル的な物は除く。
(参考:Using Edebug)
コマンド一覧
| 分類 | キー | コマンド | 説明 |
|---|---|---|---|
| ポイントの移動 | w | edebug-where | 現在のストップポイントへポイントを移動する |
| B | edebug-next-breakpoint | 次のブレークポイントがある位置へポイントを移動する(関数内で循環移動) | |
| 実行モード | S | edebug-stop | どこかのストップポイントで止める |
| SPC | edebug-step-mode | 次のストップポイントまで進んで止める | |
| n | edebug-next-mode | 式の後にあるストップポイントまで進んで止める(式の前にあるストップポイントでは止まらない) | |
| g | edebug-go-mode | 次のブレークポイントまで進んで止める | |
| G | edebug-Go-nonstop-mode | ブレークポイントを無視して進む | |
| t | edebug-trace-mode | ストップポイント毎に1秒停止しながら進む | |
| T | edebug-Trace-fast-mode | ストップポイント毎に表示を更新しながら進む | |
| c | edebug-continue-mode | ブレークポイント毎に1秒停止しながら進む | |
| C | edebug-Continue-fast-mode | ブレークポイント毎に表示を更新しながら進む | |
| C-x C-a RET | edebug-set-initial-mode | 最初の実行モードを設定する | |
| 指定位置まで実行 | h | edebug-goto-here | ポイントがある場所まで進む |
| f | edebug-forward-sexp | ポイントから 式一つ分(もしくはprefix指定数)先まで進む (現在のストップポイントからではない) | |
| o | edebug-step-out | ポイントを包む フォームの直後まで進む | |
| i | edebug-step-in | ポイントの直後 の式が関数またはマクロ呼び出しの場合、その呼び出し先に入る(引数の評価は飛ばす) | |
| デバッグの準備 | I | edebug-instrument-callee | ポイントの直後の式が関数またはマクロ呼び出しの場合、その呼び出し先をデバッグ可能にする |
| 脱出 | q | top-level | quitする。途中ハンドラでデバッグに入る |
| Q | edebug-top-level-nonstop | quitする。ハンドラがあってもデバッグに入らない | |
| a / C-] | abort-recursive-edit | 再帰編集を1段階戻る | |
| ブレークポイント | b | edebug-set-breakpoint | ポイントの場所にブレークポイントを設定する(prefix付きで一時的) |
| C-c C-t | (edebug-set-breakpoint t) | ポイントの場所にブレークポイントを一時的に設定する | |
| u | edebug-unset-breakpoint | ポイントの場所のブレークポイントを解除する | |
| U | edebug-unset-breakpoints | 現在のフォーム内の全てのブレークポイントを解除する | |
| x | edebug-set-conditional-breakpoint | 条件付きブレークポイントを設定する | |
| D | edebug-toggle-disable-breakpoint | ブレークポイントの無効化状態をトグルする | |
| ブレーク条件 | X | edebug-set-global-break-condition | 場所に関係なく成立したら止まる条件を設定する |
| 情報の表示 | r | edebug-previous-result | 直前の式の評価結果を表示する |
| d | edebug-pop-to-backtrace | バックトレースを表示する | |
| \= | edebug-temp-display-freq-count | 通過回数を一時的に表示する | |
| \= | edebug-display-freq-count | 通過回数を表示(挿入)する | |
| ? | edebug-help | ヘルプを表示する | |
| p | edebug-bounce-point | 一時的(1秒間)に実行中のカレントバッファのポイント位置を表示する | |
| 評価 | e | edebug-eval-expression | ミニバッファから式を入力して評価する |
| C-x C-e | edebug-eval-last-sexp | ポイントの直前の式を評価する | |
| E | edebug-visit-eval-list | 評価リストバッファを開く | |
| 画面構成 | v | edebug-view-outside | edebugではないウィンドウ構成に切り替える(C-x X wで戻る) |
| P | edebug-view-outside | ||
| W | edebug-toggle-save-windows |
Tips:
- iを使うと引数の評価を飛ばしてしまう。それが嫌ならばIを押してからステップ実行する。一度関数をデバッグ対象にしてしまえば次からは何もしなくても中に入る。中に入りたくない場合はf、o、hを使う。nではダメ。hがあれば他要らなくね?
練習
前進:
;; (scratchバッファ上を想定) (defun my-callee-function (a b) (message "a=%s b=%s" a b)) ;; ↓ここで C-u C-M-x または M-x edebug-eval-top-level-form (let (a b c d) ;; ■ここにいた場合 (my-callee-function ;; ←i(関数の中) ;; ↓SPC (最初のストップポイント) (cons a ;; ←n(最初の後方ストップポイント) b) (cons c d) ) ;; ←f(my-callee-functionを呼び出す式の直後) (list a b c d) ) ;; ←o(let式の直後)
無限ループ:
(defun my-edebug-practice-infinite-loop () (let ((count 0) (end nil)) ;; この変数を書き替えられれば無限ループを脱出できるのだが…… (unwind-protect ;; 無限ループはt、T、c、C、g、Gの効果を試すのにうってつけ。 ;; Sで停止。b、C-u b、u、U、x、Dでブレークポイント操作。 (while (not end) ;; 1行進む。進めなかったらバッファの先頭に移動。 (unless (zerop (forward-line)) (goto-char (point-min))) ;; pを押すと今ポイントがどこに進んだかが分かる(1秒間)。 (cl-incf count)) ;; ループ中qを押すとここに来る。Qでは来ない。 (message "count=%s" count)))) ;;←ここでC-u C-M-x ;; (my-edebug-practice-infinite-loop) ;;←ここでC-x C-e



