ocaml中的异常"Stack_overflow"

kaf*_*fka 2 ocaml

我想询问是否异常:"异常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; 
Run Code Online (Sandbox Code Playgroud)

ygr*_*rek 10

标准急救:使用-g重新编译并使用OCAMLRUNPARAM = b(参见手册)运行以查看回溯.

PS我怀疑结构比较(例如由Hashtbl.find使用),hashtbl元素中是否有任何循环引用?


gas*_*che 6

当您进入调用者函数时,堆栈会增长.while循环和尾调用不会增加堆栈,因此循环不会导致Stack_overflow错误.

正如ygrek建议的那样,如果你=在它上面使用结构比较运算符,循环数据结构可能会引发堆栈溢出.您=在代码中使用,Hashtbl模块在Pervasives.compare内部使用; 如果hashtbl键是循环的,则所有键使用操作可能会进入无限循环.在这种情况下,一个很好的修复方法是使用Hasthbl(Hashtbl.Make)的模块化形式,它允许您提供自定义的,循环感知的相等函数.

堆栈溢出的一个更常见的原因是List标准库的模块的某些功能不是尾递归的.如果应用于具有足够小的堆栈限制的足够大的列表,则它们可能导致堆栈溢出.在这种情况下,使用List提供tailrec实现的Extlib或Batteries模块是一个很好的解决方案.这不是你的问题,因为已经List.iter 尾递归.