Jump to content
david_navigator

Detect stack full for recursive routine

Recommended Posts

I have some inherited code that does some complex maths using a recursive function (i.e the function calls itself). Last night a customer had a situation where running the routine killed the app. My belief is that the app ran out of stack space due to this routine calling itself multiple times and thus died.

Is there anyway to detect this is likely to happen so that the code can be aborted with a message instead?

 

David 

Share this post


Link to post
3 hours ago, david_navigator said:

I have some inherited code that does some complex maths using a recursive function (i.e the function calls itself). Last night a customer had a situation where running the routine killed the app. My belief is that the app ran out of stack space due to this routine calling itself multiple times and thus died.

Is there anyway to detect this is likely to happen so that the code can be aborted with a message instead?

 

David 

There is a EStackoverflow exception type defined in System.Sysutils but it has been deprecated for several Delphi versions. A stack overflow cannot be trapped reliably via try except and recovering from it is practically impossible. What you can do, however, is to increase the stack size used by the program (in the linker part of the program options). Of course that is a band aid that does not protect from future failures due to an even more pathological set of input data.

 

You can look into rewriting the algorithm to avoid recursion. Intead of relying on local variables to hold intermediate results (i.e. store them on the stack) you store this data into a record and manage a stack of these records yourself. This gives you much more control over the memory used, as well as removing the hard limit imposed by the default stack size.

  • Thanks 1

Share this post


Link to post

Thanks. This is the first time it's fallen over in 20 years so not too concerned. I just wondered if there was a call like "is there enough stack space left for me to call this routine again" kind of thing.

Share this post


Link to post

You can setup counter and check it. The catch is that you never know how much space is occupied on the stack by single call. First I'd add logging of enters and leaves to that function and see whether it is really the source of problems. Then you'd have to decide whether this consumption is acceptable by algo (like matrix reverse - big matrix means big nesting, that's not an issue in algo but in input) or it's a algo's flaw (endless/excess recursion). In the former case you can try to optimize the code. Remember any local variable eats stack - probably you can reduce their number by using heap or object fields. Function parameters, if there's many of them, also consume stack so you can unite them into a record (but store it in heap otherwise it eats stack of the caller).

Edited by Fr0sT.Brutal

Share this post


Link to post

@david_navigator no-one mentioned that 
a) if you can arrange for calculation by tail-calls, Delphi can eliminate runaway stack increases.
b) there are techniques to linearise some recursive functions by decomposing the single function into multiple functions with extra state.
c) it may be possible to memoise calculations that might be repeated.  

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×