2

I wanted to ask if the exception :"exception Stack_overflow" could be caused an infinite loop , particularly, the exception occurs in the following code :

    ( *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; 
2
  • 2
    To be more idiomatic to functional programming, you should replace your Stack with a list, and replace the while loop with a recursive call. Is there a reason why this section is programmed in an imperative style? Commented Jan 5, 2011 at 15:04
  • 2
    Generally no, while loops won't cause a stack overflow - there is no stack. Commented Jan 5, 2011 at 16:40

3 Answers 3

10

Standard first-aid : recompile with -g and run with OCAMLRUNPARAM=b (cf manual) to see backtrace.

PS I would suspect structural comparison (e.g. used by Hashtbl.find), are there any circular references in hashtbl elements?

Sign up to request clarification or add additional context in comments.

Comments

6

The stack grows when you enter into a caller function. while loops and tail-calls do not grow the stack, so a Stack_overflow error cannot result from such as loop.

As ygrek suggested, a cyclic data structure may provoke a stack overflow if you use the structural comparison operator = on it. You use = in your code, and the Hashtbl module uses Pervasives.compare internally; if the hashtbl keys are cyclic, all key-using operations may run into infinite loop. In that case, a good fix would be to use the modularized form of Hasthbl (Hashtbl.Make) which allows you to provide a custom, cyclicity-aware equality function.

A more common cause for stack overflow is the fact that some of the functions of the List module of the standard library are not tail-recursive. If applied to big enough list with a small enough stack limit, they may cause stack overflows. In this case, using the List module of Extlib or Batteries -- which provides tailrec implementations -- is a good fix. This is not your problem here however, as List.iter is tail-recursive already.

Comments

0

The other answers address the programming style, which is good: if you have a huge stack and can fix it programatically, that is best.

However, if there is nothing you can do then note that ulimit -s controls the max stack size. For deep stacks in Coccinelle I was able to finish the transform with the following:

ulimit -s $((1024*1024))

Note that this specifies a 1GB stack and used about 2.4GB of RAM, but it worked!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.