gprolog:异常后获取堆栈跟踪
gprolog: Getting a stacktrace after an exception
在使用 gprolog 时,我经常遇到没有任何类型的行号或上下文的异常:
uncaught exception: error(instantiation_error,(is)/2)
没有任何上下文。我知道我可以做一个 trace
但是用 trace
调试它会花很长时间,因为在到达错误发生的地方之前我需要执行很多事情。
知道如何获得这个堆栈跟踪吗?或者动态 trace
/ notrace
?
编辑:或者只是自动打印整个 trace
输出。
您可以 trace/0
和 leash/1
只有 异常 端口,例如:
?- trace.
?- leash([exception]).
然后你 运行 你的程序,它会在屏幕上打印一条轨迹,但只有在发生异常时才会停止。在那里你可以通过按字母 g
.
查看 "stack trace"(祖先)
@gusbro 的回答 (s(X)
) 向您展示了如何使用 GNU 的调试器稍微解决这个问题。但是,如果您无力查看所有正在进行的打印,或者它太慢了,您可以考虑在 Scryer 中作为 library(debug)
使用以下“调试器”。
我个人不使用 Prolog 系统提供的调试器,原因很简单,因为它们中的大多数打印太多,本身经常有错误,并且有自己特定的不断变化的约定,我无力学习。
:- op(900, fx, [@,$,$-]).
$-(G_0) :-
catch(G_0, Ex, ( portray_clause(exception:Ex:G_0), throw(Ex) ) ).
$(G_0) :-
portray_clause(call:G_0),
$-G_0,
portray_clause(exit:G_0).
@(G_0) :-
( $-G_0
*-> true
; portray_clause(badfail:G_0),
throw(goal_failed(G_0))
).
:- op(950, fy, *).
*(_).
要使用它,只需在特定目标前添加 $-
、$
或 @
。
$-
意思是:只有通过这个目标的信号异常
$
另外显示调用和退出
@
确保至少有一个答案,如果没有,则报告并抛出异常。
谨慎使用以上注释!
*
移除目标。这是为了泛化在纯单调程序中进行程序修改/program-slicing 的程序。在 意外失败 的情况下你需要这个。有关如何使用它的示例,请参阅以下 answers/debugging 个会话
1,
2,
3,
4,
5,
6,
7,
8,
9,
10.
_/*term*/
用匿名变量替换术语。这比单独 *
更广泛地概括了一个程序。示例会话:
1,
2,
3,
4,
5,
6,
7,
8,
9,
10.
通过这种方式,您可以显着减少观看的信息。
在其他支持meta_predicate
指令的系统中,如SICStus、YAP和SWI,在前面添加以下指令:
:- meta_predicate(( $-(0), $(0), @(0) )).
在使用 gprolog 时,我经常遇到没有任何类型的行号或上下文的异常:
uncaught exception: error(instantiation_error,(is)/2)
没有任何上下文。我知道我可以做一个 trace
但是用 trace
调试它会花很长时间,因为在到达错误发生的地方之前我需要执行很多事情。
知道如何获得这个堆栈跟踪吗?或者动态 trace
/ notrace
?
编辑:或者只是自动打印整个 trace
输出。
您可以 trace/0
和 leash/1
只有 异常 端口,例如:
?- trace.
?- leash([exception]).
然后你 运行 你的程序,它会在屏幕上打印一条轨迹,但只有在发生异常时才会停止。在那里你可以通过按字母 g
.
@gusbro 的回答 (s(X)
) 向您展示了如何使用 GNU 的调试器稍微解决这个问题。但是,如果您无力查看所有正在进行的打印,或者它太慢了,您可以考虑在 Scryer 中作为 library(debug)
使用以下“调试器”。
我个人不使用 Prolog 系统提供的调试器,原因很简单,因为它们中的大多数打印太多,本身经常有错误,并且有自己特定的不断变化的约定,我无力学习。
:- op(900, fx, [@,$,$-]).
$-(G_0) :-
catch(G_0, Ex, ( portray_clause(exception:Ex:G_0), throw(Ex) ) ).
$(G_0) :-
portray_clause(call:G_0),
$-G_0,
portray_clause(exit:G_0).
@(G_0) :-
( $-G_0
*-> true
; portray_clause(badfail:G_0),
throw(goal_failed(G_0))
).
:- op(950, fy, *).
*(_).
要使用它,只需在特定目标前添加 $-
、$
或 @
。
$-
意思是:只有通过这个目标的信号异常
$
另外显示调用和退出
@
确保至少有一个答案,如果没有,则报告并抛出异常。
谨慎使用以上注释!
*
移除目标。这是为了泛化在纯单调程序中进行程序修改/program-slicing 的程序。在 意外失败 的情况下你需要这个。有关如何使用它的示例,请参阅以下 answers/debugging 个会话
1,
2,
3,
4,
5,
6,
7,
8,
9,
10.
_/*term*/
用匿名变量替换术语。这比单独 *
更广泛地概括了一个程序。示例会话:
1,
2,
3,
4,
5,
6,
7,
8,
9,
10.
通过这种方式,您可以显着减少观看的信息。
在其他支持meta_predicate
指令的系统中,如SICStus、YAP和SWI,在前面添加以下指令:
:- meta_predicate(( $-(0), $(0), @(0) )).