如何让 Erlang 调试器执行条件中断?

How do you get the Erlang debugger to execute a conditional break?

给定一个正数 N,我的 print_even() 函数打印出 1 和 N 之间的所有偶数:

-module(my).
-compile(export_all).

print_even(N) when N>0 -> even_helper(1, N).

even_helper(Current, N) when Current =< N ->
    io:format("(Current = ~w)~n", [Current]),
    case Current rem 2 of
        0 -> io:format("Number: ~p~n", [Current]);
        _ -> do_nothing
    end,
    even_helper(Current+1, N);
even_helper(Current, N) when Current > N ->
    ok.

这是一些示例输出:

28> my:print_even(10).
(Current = 1)
(Current = 2)
Number: 2
(Current = 3)
(Current = 4)
Number: 4
(Current = 5)
(Current = 6)
Number: 6
(Current = 7)
(Current = 8)
Number: 8
(Current = 9)
(Current = 10)
Number: 10
ok

下面是我用于条件中断的代码:

-module(c_test).
-compile(export_all).

c_break(Bindings) ->
    case int:get_bindings('Current', Bindings) of
        {value, 3}  -> true;
        _           -> false
    end.

我在 print_even():

中的以下行设置了条件中断
    case Current rem 2 of

...根据 Erlang debugger docs 应该是合法的。但是无论我做什么,我都无法执行 c_break() 函数。当 Current 等于 3 时,我希望执行在断点处停止,但代码运行到完成,并跳过断点。我什至尝试过:

c_break(Bindings) ->
    case int:get_bindings('Current', Bindings) of
        _  -> true;
    end.

但是执行仍然不会在断点处停止。

更新: 如果我对条件中断使用以下函数,我 可以 停止执行:

c_break(_) ->
    true.

如果我将其更改为:

c_break(X) ->
    io:format("~w~n", [X]),
    true.

...然后再次执行不会停止。

!@#$!@#$@!!应该是:

int:get_binding()
              ^
              |

不是:

int:get_bindings() 
               ^
               |

即便如此,重新编译模块也未能成功停止执行。为了让事情正常工作,我不得不退出调试器:我关闭了所有调试器 windows,然后我发出了命令:

82> debugger:stop().
ok 

(我找不到函数 debugger:stop() 的任何信息,所以我不知道这是否有必要,甚至不知道它是否有任何作用。)

然后我重新编译了两个模块:

83> c(my, [debug_info]).
{ok,my}
84> c(c_test).
{ok,c_test}

然后:

85> debugger:start().
{ok,<0.305.0>}

debugger:start() 启动 Monitor window,并在监视器 window 处于活动状态时选择菜单项:

Module > Interpret 

...我从弹出窗口中选择了 my.erl——其中 my.erl 是包含我要停止执行的函数的模块。

然后在监视器 window 仍处于活动状态的情况下,我选择了菜单项:

 Break>Conditional Break 

...然后我填了资料。您也可以双击监视器window中显示的模块名称,然后使用打开的View Module window设置断点。 View Module window 显示您的源代码,window 还有一个 Break 菜单项,它允许您设置各种类型的断点。在视图模块 window 中,您可以使用创建行断点的快捷方式,即常规断点:您可以通过双击代码中的一行来设置断点。

最后:

86> my:print_even(10).  
(Current = 1)
(Current = 2)
Number: 2
(Current = 3)

万岁!

然后我双击监视器 window 中列出的进程,然后打开一个附加进程 window。附加进程 window 显示代码中的执行停止位置,它为您提供逐步执行代码的方法。

返回监视器 window,如果选中复选框 On Break,则当执行在断点处停止时,附加进程 window 将自动打开。据我所知,每次 运行 您的代码都需要打开一个新的附加进程 window。

顺便说一句,模块名c_test和函数名c_break()可以是任何名字。它们的名称并不重要,例如我将模块名称更改为 conditional_breaks 并将函数名称更改为 break1().