Debug in R #1: The basics of interactive debugging


インタラクティブ・デバッグの基本

デバッグは基本的にdebugとかbrowserとかでインタラクティブ・デバッグモードに入って行うことが多い。使えるコマンドは以下の通り。

  • n (または空行でリターン): 現在の式を実行。
  • c (または cont): デバッグモードを終了して、以降の式を実行。
  • Q: デバッグモードを終了。以降の式は実行されない。
  • where: コールスタック(関数呼び出しのスタック)を表示。

その他の入力は、Rのコンソール上での入力と同じように評価される。ls()で変数リストを表示するとかは便利。変数名を入れればその変数がprintされる。

実行例

関数定義

g <- function() {
	d <- 1
	e <- 2
	print(3)
}
f <- function() {
	a <- 1
	g() # gを呼び出す。
	b <- 2
}

実行例

> debug(g) # gの最初にブレークポイントを仕込む
> f() # fを呼び出す。中でデバッグモードに入り、関数定義が表示される。
debugging in: g()
debug: {
    d <- 1
    e <- 2
    print(3)
}
Browse[2]> where # コールスタックの表示
where 1: g()
where 2: f()

Browse[2]> n # 次の式へ
debug: d <- 1 # 次に評価される式が表示される(まだ評価されていない)。
Browse[2]> n # 式を評価して、次の式へ。
debug: e <- 2 # これは次に評価される式。まだ評価されていない。
Browse[2]> d # d <- 1はすでに評価されたので、dは存在する。
[1] 1
Browse[2]> e # e <- 1はまだ評価されてない。
 エラー:  オブジェクト 'e' がありません 
Browse[2]> ls() # ls()で変数一覧を表示。
[1] "d"
Browse[2]> n # 次へ。
debug: print(3)
Browse[2]> ls() # 今度はeもある。
[1] "d" "e"
Browse[2]> c # デバッグ終了して継続。
[1] 3 # 継続なのでprint(3)が実行される。Qで抜けるとこれは実行されない。
exiting from: g()

ステップアウト

内側の方の関数でデバッグしてて、その外側に出たい時は、browserSetDebugcを組み合わせれば、ステップアウトできる。

実行例

> f()
debugging in: g()
debug: {
    d <- 1
    e <- 2
    print(3)
}
Browse[2]> where # コールスタック。toplevel -> f -> gで、いまgにいる。
where 1: g()
where 2: f()

Browse[2]> browserSetDebug(1) # 一個外側(=f)で止めるように設定。
Browse[2]> c # 継続
[1] 3 # print(3)が実行されて
exiting from: g() # g()を抜ける
debug: b <- 2 # f()の中の、g()を実行した後のところで止まってる。これは次に評価される式。
Browse[2]> where # コールスタック
where 1: f()

Browse[2]> ls() # aはすでに評価されている。
[1] "a"
Browse[2]> n

ステップイン

次の評価式に関数が含まれていた時に、その関数に入っていってデバッグする方法は提供されていない(多分)。だけど、その場でdebugまたはdebugonceを使うことでステップインっぽいことはできる。

関数定義

h <- function() {
	a <- rnorm(100)
	b <- sd(a) # hのデバッグ中に、sdの中にステップインしたい。
	print(b)
}

実行例

> debug(h) # hをデバッグ設定。
> h()
debugging in: h()
debug: {
    a <- rnorm(100)
    b <- sd(a)
    print(b)
}
Browse[2]> n
debug: a <- rnorm(100)
Browse[2]> n
debug: b <- sd(a) # 次にsd(a)が実行されるので、
Browse[2]> debugonce(sd) # sdを一回だけデバッグしよう
Browse[2]> n # sd(a)が実行される
debugging in: sd(a) # sd(a)でのデバッグに突入。
debug: {
    if (is.matrix(x)) 
        apply(x, 2, sd, na.rm = na.rm)
    else if (is.vector(x)) 
        sqrt(var(x, na.rm = na.rm))
    else if (is.data.frame(x)) 
        sapply(x, sd, na.rm = na.rm)
    else sqrt(var(as.vector(x), na.rm = na.rm))
}
Browse[3]> n
debug: if (is.matrix(x)) apply(x, 2, sd, na.rm = na.rm) else if (is.vector(x)) sqrt(var(x, 
    na.rm = na.rm)) else if (is.data.frame(x)) sapply(x, sd, 
    na.rm = na.rm) else sqrt(var(as.vector(x), na.rm = na.rm))
Browse[3]> c # 特に今はやることないので、継続して抜ける。
exiting from: sd(a) # sd(a)を抜ける
debug: print(b) # 今b <- sd(a)が評価し終わったところで、これは次の評価式。
Browse[2]> ls() # bがある。
[1] "a" "b"
Browse[2]> b
[1] 0.9161782
Browse[2]> n
[1] 0.9161782
exiting from: h()

debugonceは一回だけデバッグする用の関数(普通のdebugでは、その関数が呼び出されるたびにデバッグモードに入る)。
上の例ではsd(a)の実行の直前でdebugonceしてるけど、別に直前じゃなくても、実行前ならいつでもいい。

One thought on “Debug in R #1: The basics of interactive debugging

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s