我想询问是否异常:“异常Stack_overflow”可能导致无限循环,特别是,以下代码中发生异常:
( *the loop "while" should stop when both stacks are empty*)
while (not (Stack.is_empty stackFalse) )|| ( not (Stack.is_empty stackTrue)) do
(
if (not ( Stack.is_empty stackTrue )) then
(
let q1 = Stack.pop stackTrue in
let (_,_,ptrs) = fst (Hashtbl.find graph ( fst q1) ) in
List.iter ( fun elem ->
let app = Hashtbl.find graph elem in
let (typeNode,last,ptrs') = fst app in
if typeNode = "Or-node" then
(
Stack.push (elem,true) stackTrue;
Hashtbl.add labeled elem true
)
else if last = false then
Hashtbl.replace graph elem ((typeNode,true,ptrs'),snd app)
else
(
Stack.push (elem,true) stackTrue;
Hashtbl.add labeled elem true
) ) ptrs ;
);
if (not ( Stack.is_empty stackFalse )) then
(
let q2 = Stack.pop stackFalse in
let (_,_,ptrs1) = fst (Hashtbl.find graph (fst q2) )in
List.iter ( fun elem ->
let app = Hashtbl.find graph elem in
let (typeNode,last,ptrs') = fst app in
if typeNode = "And-node" then
(
Stack.push (elem,false) stackFalse;
Hashtbl.add labeled elem false
)
else if last = false then
Hashtbl.replace graph elem ((typeNode,true,ptrs'),snd app)
else
(
Stack.push (elem,false) stackFalse;
Hashtbl.add labeled elem false
) ) ptrs1 ;
);
)
done;
答案 0 :(得分:10)
标准急救:使用-g重新编译并使用OCAMLRUNPARAM = b(参见手册)运行以查看回溯。
PS我怀疑结构比较(例如由Hashtbl.find使用),hashtbl元素中是否有任何循环引用?
答案 1 :(得分:6)
当您进入调用者函数时,堆栈会增长。 while
循环和尾调用不会增加堆栈,因此循环不会导致Stack_overflow错误。
正如ygrek建议的那样,如果在结构比较运算符=
上使用循环数据结构,则可能会引发堆栈溢出。您在代码中使用=
,Hashtbl
模块在内部使用Pervasives.compare
;如果hashtbl键是循环的,则所有键使用操作可能会进入无限循环。在这种情况下,一个好的解决方法是使用Hasthbl
(Hashtbl.Make
)的模块化形式,它允许您提供自定义的,循环感知的相等函数。
堆栈溢出的一个更常见的原因是标准库的List
模块的某些函数不是尾递归的。如果应用于具有足够小的堆栈限制的足够大的列表,则它们可能导致堆栈溢出。在这种情况下,使用Extlib或Batteries的List
模块 - 提供tailrec实现 - 是一个很好的解决方案。这不是你的问题,因为List.iter
已经尾递归了。