2

I have a recursion algorithm that may go into extrordinary depths and I don't want a stack overflow. Is there a way of storing function call stacks on the heap rather than the stack?

Michael Scofield
  • 128
  • 2
  • 11
  • yes if you refactor the recursion into iteration – 463035818_is_not_an_ai May 06 '19 at 14:35
  • Have you actually had a stack overflow? You may be trying to fix a problem that doesn't exist. You could always convert your recursive function to an iterative one. – Kevin May 06 '19 at 14:36
  • Why don't you try rewriting this using iteration instead ? – rranjik May 06 '19 at 14:36
  • In general: No. But maybe you can reduce your stack frame size? Or ask the operating system for a larger stack? Or use an iterative algorithm? – johannes May 06 '19 at 14:36
  • 3
    Maybe this: https://stackoverflow.com/questions/159590/way-to-go-from-recursion-to-iteration – drescherjm May 06 '19 at 14:36
  • 3
    How deep is extraordinary? Show us your code, in an MCVE. – 2785528 May 06 '19 at 14:37
  • 2
    An extremely literal answer could point to `pthread_attr_setstack`. If you are in a posixy environment and do your calculation in a thread, you can put your stack where you like and allocate as much as you want for it. Though refactoring the algorithm to not use recursion seems to be a better idea. –  May 06 '19 at 14:47
  • I do agree a non-recursive algorithm is better to use, but for the sake of learning I'd like to find a way to do this too. – Michael Scofield May 06 '19 at 14:58
  • @jakub_d Pretty much answered it, extending the stack space is what I wanted. Can you put it into the answers section so I can mark it? – Michael Scofield May 06 '19 at 15:03
  • 2
    If you make sure your algorithm is tail-recursive, then the compiler will automatically convert the recursion into iteration. See https://en.wikipedia.org/wiki/Tail_call and https://stackoverflow.com/questions/2693683/tail-recursion-in-c – Nikos C. May 06 '19 at 15:30

3 Answers3

2

If you really want to extend your stack space, there is always pthread_attr_setstack, it is available in posix-like environments, requires you to do your work in a thread and lets you allocate as much as you want. It requires the memory to be read/write (not a problem for the heap) and somewhat aligned, consult your man pages for the exact details...

1

If you have lots of variables declared in the function to be stored on the stack, especially large arrays, you could just move the variables to the heap.

Aaron Zimmerman
  • 161
  • 1
  • 4
1

I have a recursion algorithm that may go into extrordinary depths and I don't want a stack overflow. Is there a way of storing function call stacks on the heap rather than the stack?

Have you explored a functor?

In the following, note that

  • all (normal) functions of a class include the hidden " T* this " parameter.

  • thus any data attribute of the class is directly accessible to each function.

Maybe your 'Functor packaging' can lighten the recursion stack load, eliminating much of the parameter passing between the calls.

Simple Example:

class T934c_t //  tail recursive, return string which contains step pattern,
{
   stringstream  ss;        // data attributes ALL pass function-to-function
   int64_t maxPtrnHgtWdth;  //   through the hidden this pointer.

public:
   string operator()(int64_t max)
      {
         maxPtrnHgtWdth = max;  // <<< save to functor data attributes
         exec();                // <<< filled in during execution
         return ss.str();       // return result of execution.
      }

private:
   void exec ()
      {
         ss << "\n\n\n  string T934c_t()(int64_t): -->"
            << " void exec (int64_t)     (" << maxPtrnHgtWdth
            << ")\n         tail recursive, return string which contains step pattern, ";

         execR (maxPtrnHgtWdth); // entry to recursive code
      }
   //                  8..1
   void execR (int64_t step)     // recursive 
      {
         if (0 >= step) return;  // recursion termination
         dotPndLine (step-1);    // build each line with dots and pound signs
         execR (step-1);         // tail recursion
      }
   //                       7..0
   void dotPndLine (int64_t step) // single line
      {
         ss << "\n  ";
         dotR (step);                 // 7..0  dots
         pndR (maxPtrnHgtWdth-step);  // 1..8  pound sign
         ss << ' ';
      }
   //                 7..0
   void dotR (int64_t dotCt) { // recursive
      if (0 >= dotCt) return;  // recursion termination
      ss << '.';               // simple execution
      dotR (dotCt-1);          // tail recursion
   }
   //                 1..8
   void pndR (int64_t pndCt) { // recursive
      if (0 >= pndCt)  return; // recursion termination
      ss << '#';               // simple
      pndR (pndCt-1);          // tail recursion
   }
}; // class T934c_t
2785528
  • 5,438
  • 2
  • 18
  • 20
  • Are you familiar with hailstone? The sizeof(myHailstoneClass) ended up at 1000 bytes, and it recursed (in that peculiar non-pattern) with 5 billion start values, confirming each as a magic number. No SO. (in less than 42 seconds) – 2785528 May 06 '19 at 19:22