Why do recursive WebGL functions not cause a stack overflow? - recursion

This is my first question on StackOverflow, so forgive any breaches in protocol.
I'm learning WebGL in a computer graphics class in college. While learning to make a square rotate on the screen, my classmates and I noticed the following code in the render function:
function render()
{
gl.clear(gl.COLOR_BUFFER_BIT);
theta += 0.1;
gl.uniform1f(thetaLoc, theta);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
render();
}
What we don't understand, and our professor was not able to give us an adequate answer, is why this code does not cause a stack overflow since it calls itself recursively. We ran the code, and it doesn't cause any problems, but we don't understand why.
We weren't able to find an answer to this in our textbook or online. If anyone can explain it, I'll pass it on to my classmates. Thanks in advance.

That does cause a stack overflow. When I run it I get
Uncaught RangeError: Maximum call stack size exceeded
I think you probably saw code like this
function render() {
...
requestAnimationFrame(render);
}
render();
In that case it's not recursive. The render function is requesting an animation frame and then exiting. Then the browser renders the next frame it calls render again.

Related

Cause stack overflow through recursion

I have been working on implementing a priority queue of strings in c++ using a binary tree.
As I think the simplicity of recursion is great. I am not going to post code as I have already spent a long time today with the debugger and I am not asking for someone to debug for me, but basically after implementing recursive methods to dequeue and insert elements and testing correct behavior with up to 1000 random strings I have used a test hub that tries to enqueue 10000 random strings and I have a stack overflow error. After this, I have changed my recursive methods for others that use a pointer cursor to scan my tree to insert and dequeue using the same logic and it has not crashed as I expected (i have coded it almost as a linked list).
The question is then, Can I cause stack overflow through recursion even if I use to pass by reference?
These recursive methods are part of a class and defined as private.
I hope the question is not vague but I am still not experienced enough in c++.
Thanks a lot for your help!
In recursion you're calling your function again and again. On every call you use the stack memory for parameters, stack variables and more. So basicly the answer is definitely yes, a deep recursion can cause a stack overflow.

Depth first traversal

I'm trying to optimise a html parser for a Roku application I'm helping to develop. The parser currently takes too long to parse the data (8 seconds) and it does this by recursivly traversing the children of each tag encountered within a for each loop.
parser (nodes):
for each node in nodes
if node.isTag
parser(node.nodes)
else if node.isBlock
text.push(node)
something akin to that, although much more convoluted! I'm assuming it's slow because it's recursive and there is no tail recursion optimisation on the platform etc
I'm not too sure how to implement a stack to remove the recursiveness from this - I've tried using GoTo but that didn't seem to work :/
Can anyone provide some insight, and or whether you think the problem might be caused by the recursion?
What are you trying to achieve?
Some boxes are slow, there is only a certain amount of optimisation you can apply. If you need to parse the whole document, it usually takes what it takes. We had similar problem, app froze for a few seconds, looking like it's crashed but we got around it by displaying asynchronous spinning icon.

Why is this not an example of recursion?

So, I saw someplace (I'm not sure where off the top of my head, but if I recall it I will post a link to it) that the following code was not example of recursion:
void f() {
f();
}
Now, this is a function that calls itself (albeit, infinitely). Why would that not be an example of recursion? It might not be the best example, but why would they go so far as stating that it's not recursion at all?
That's definitely an example of a recursive function, based solely on the definition of "recursive". Simply speaking, a recursive function is any one that calls itself.
It's hard to explain why someone said it wasn't without seeing their claim in context (and hopefully an attempt at a justification for that claim).
That said, it's not a very useful recursive function, and perhaps that was the point they were driving at. Any program that calls that function will eventually crash after it overflows the stack. Sometimes, this is called a "Stack Overflow" error. :-)
Useful recursive functions have to contain some kind of conditional code that causes the recursion to stop eventually.
Your code example does not have a way to terminate and would go on forever, likely causing a stack overflow exception. Recursive functions have a simple way to terminate through a base case condition. Read this article for a proper definition and explanation.
That is definitely recursion, and here are some notes form the University of Wisconsin-Madison. Actually using void f() as the example http://pages.cs.wisc.edu/~vernon/cs367/notes/6.RECURSION.html
The site could of been trying to drive home a point of how not to do recursion .. not sure without the source link.
It is example of recursion but there is no way to end it , you have to terminate it using condition.

Recursion vs loops

I'm facing a problem where both recursion and using a loop seem like natural solutions. Is there a convention or "preferred method" for cases like this? (Obviously it is not quite as simple as below)
Recursion
Item Search(string desired, Scope scope) {
foreach(Item item in scope.items)
if(item.name == desired)
return item;
return scope.Parent ? Search(desired, scope.Parent) : null;
}
Loop
Item Search(string desired, Scope scope) {
for(Scope cur = scope; cur != null; cur = cur.Parent)
foreach(Item item in cur.items)
if(item.name == desired)
return item;
return null;
}
I favor recursive solutions when:
The implementation of the recursion is much simpler than the iterative solution, usually because it exploits a structural aspect of the problem in a way that the iterative approach cannot
I can be reasonably assured that the depth of the recursion will not cause a stack overflow, assuming we're talking about a language that implements recursion this way
Condition 1 doesn't seem to be the case here. The iterative solution is about the same level of complexity, so I'd stick with the iterative route.
If performance matters, then benchmark both and choose on a rational basis. If not, then choose based on complexity, with concern for possible stack overflow.
There is a guideline from the classic book The Elements of Programming Style (by Kernighan and Plauger) that algorithm should follow data structure. That is, recursive structures are often processed more clearly with recursive algorithms.
Recursion is used to express an algorithm that is naturally recursive in a form that is more easily understandable. A "naturally recursive" algorithm is one where the answer is built from the answers to smaller sub-problems which are in turn built from the answers to yet smaller sub-problems, etc. For example, computing a factorial.
In a programming language that is not functional, an iterative approach is nearly always faster and more efficient than a recursive approach, so the reason to use recursion is clarity, not speed. If a recursive implementation ends up being less clear than an iterative implementation, then by all means avoid it.
In this particular case, I would judge the iterative implementation to be clearer.
If you are using a functional language (doesn't appear to be so), go with recursion. If not, the loop will probably be better understood by anyone else working on the project. Of course, some tasks (like recursively searching a directory) are better suited to recursion than others.
Also, if the code cannot be optimized for tail end recursion, the loop is safer.
Well I saw tons of answers and even accepted answer but never saw the correct one and was thinking why...
Long story short :
Always avoid recursions if you can make same unit to be produced by loops!
How does recursion work?
• The Frame in Stack Memory is being allocated for a single function call
• The Frame contains reference to the actual method
• If method has objects, the objects are being put into Heap memory and Frame will contain reference to that objects in Heap memory.
•These steps are being done for each single method call!
Risks :
• StackOverFlow when the stack has no memory to put new recursive methods.
• OutOfMemory when the Heap has no memory to put recursive stored objects.
How Does loop work?
• All the steps before, except that the execution of repeatedly code inside the loop will not consume any further data if already consumed.
Risks :
• Single risk is inside while loop when your condition will just never exist...
Well that won't cause any crashes or anything else, it just won't quit the loop if you naively do while(true) :)
Test:
Do next in your software:
private Integer someFunction(){
return someFunction();
}
You will get StackOverFlow exception in a second and maybe OutOfMemory too
Do second:
while(true){
}
The software will just freeze and no crash will happen:
Last but not least - for loops :
Always go with for loops because this or that way this loop somewhat forces you to give the breaking point beyond which the loop won't go, surely you can be super angry and just find a way to make for loop never stop but I advice you to always use loops instead of recursion in sake of memory management and better productivity for your software which is a huge issue now days.
References:
Stack-Based memory allocation
Use the loop. It's easier to read and understand (reading code is always a lot harder than writing it), and is generally a lot faster.
It is provable that all tail-recursive algorithms can be unrolled into a loop, and vice versa. Generally speaking, a recursive implementation of a recursive algorithm is clearer to follow for the programmer than the loop implementation, and is also easier to debug. Also generally speaking, the real-world performance of the loop implementation will be faster, as a branch/jump in a loop is typically faster to execute than pushing and popping a stack frame.
Personally speaking, for tail-recursive algorithms I prefer sticking with the recursive implementation in all but the most-performance-intensive situations.
I prefer loops as
Recursion is error-prone
All the code remains into one function / method
Memory and speed savings
I use stacks (LIFO schema) to make the loops work
In java, stacks is covered with Deque interface
// Get all the writable folders under one folder
// java-like pseudocode
void searchWritableDirs(Folder rootFolder){
List<Folder> response = new List<Folder>(); // Results
Deque<Folder> folderDeque = new Deque<Folder>(); // Stack with elements to inspect
folderDeque.add(rootFolder);
while( ! folderDeque.isEmpty()){
Folder actual = folder.pop(); // Get last element
if (actual.isWritable()) response.add(actual); // Add to response
for(Folder actualSubfolder: actual.getSubFolder()) {
// Here we iterate subfolders, with this recursion is not needed
folderDeque.push(actualSubfolder);
}
}
log("Folders " + response.size());
}
Less complicated, more compact than
// Get all the writable folders under one folder
// java-like pseudocode
void searchWritableDirs(Folder rootFolder){
List<Folder> response = new List<Folder>(); // Results
rec_searchWritableDirs(actualSubFolder,response);
log("Folders " + response.size());
}
private void rec_searchWritableDirs(Folder actual,List<Folder> response) {
if (actual.isWritable()) response.add(actual); // Add to response
for(Folder actualSubfolder: actual.getSubFolder()) {
// Here we iterate subfolders, recursion is needed
rec_searchWritableDirs(actualSubFolder,response);
}
}
The latter has less code, but two functions and it's harder to understand code, IMHO.
I would say the recursion version is better understandable, but only with comments:
Item Search(string desired, Scope scope) {
// search local items
foreach(Item item in scope.items)
if(item.name == desired)
return item;
// also search parent
return scope.Parent ? Search(desired, scope.Parent) : null;
}
It is far easier to explain this version. Try to write a nice comment on the loop version and you will see.
I find the recursion more natural, but you may be forced to use the loop if your compiler doesn't do tail call optimization and your tree/list is too deep for the stack size.
If the system you're working on has a small stack (embedded systems), the recursion depth would be limited, so choosing the loop-based algorithm would be desired.
I usually prefer the use of loops. Most good OOP designs will allow you to use loops without having to use recursion (and thus stopping the program from pushing all those nasty parameters and addresses to the stack).
It has more of a use in procedural code where it seems more logical to think in a recursive manner (due to the fact that you can't easily store state or meta-data (information?) and thus you create more situations that would merit it's use).
Recursion is good for proto-typing a function and/or writing a base, but after you know the code works and you go back to it during the optimization phase, try to replace it with a loop.
Again, this is all opinionated. Go with what works best for you.
You can also write the loop in a more readable format. C's for(init;while;increment) have some readability drawbacks since the increment command is mentioned at the start but executed at the end of the loop.
Also YOUR TWO SAMPLES ARE NOT EQUIVALENT. The recursive sample will fail and the loop will not, if you call it as: Search(null,null). This makes the loop version better for me.
Here are the samples modified (and assuming null is false)
Recursion (fixed and tail-call optimizable)
Item Search(string desired, Scope scope) {
if (!scope) return null
foreach(Item item in scope.items)
if(item.name == desired)
return item;
//search parent (recursive)
return Search(desired, scope.Parent);
}
Loop
Item Search(string desired, Scope scope) {
// start
Scope cur = scope;
while(cur) {
foreach(Item item in cur.items)
if(item.name == desired)
return item;
//search parent
cur = cur.Parent;
} //loop
return null;
}
If your code is compiled it will likely make little difference. Do some testing and see how much memory is used and how fast it runs.
Avoid recursion. Chances are that piece of code will have to be maintained eventually at some point and it'll be easier if it is not done with recursion. Second, it'll most likely have a slower execution time.

Why is goto poor practise? [duplicate]

This question already has answers here:
Closed 14 years ago.
This question is a duplicate of Goto Still Considered Harmful. If you wish to discuss this further please use the original question.
Why exactly is GOTO poor programming practise? It makes sense on some occasions to use it.
Note that Djkstra wrote "GOTO Considered Harmful", not "GOTO Considered Deadly". It has its places. Unfortunately, the judgement to know when to use it comes after you've got some experience in maintaining other people's code, especially code that was written years ago by people who no longer work in your company. Thus, it's best to avoid goto as much as you can until you have that experience.
It encourages bad coding style, basically. See: Goto Considered Harmful [pdf]
It can rapidly lead to spaghetti code.
It means you haven't designed the code procedurally.
If you build your whiles and ifs properly, you should rarely ever need goto.
Rarely is the key word. There are times where it's useful. In that sense, many people nowadays just explicitly throw and catch exceptions, just to avoid the dreaded goto.
Because the structure of the code can be difficult to follow.
This
y:
// do more stuff
goto x
p:
// do stuff
// then done
goto y;
x:
// do a bunch of stuff
if (...)
goto y;
else
goto p;
done:
is much less clear than
int main()
{
x();
}
function p()
{
if (...)
{
return;
}
}
function x()
{
if (...)
{
return;
}
else
{
p();
}
}
GOTO short circuits your control flow, thereby undermining your design and opening the door to debug and maintenance nightmares.
Readability becomes a problem, and flow of logic can have unintended effects by the use of goto.
I think its funny that the .net compiler will change some case/switch statements to use goto.
In some cases it makes sense. But, in the majority of cases use of it it considered poor practice because it can make the execution path of code tricky to read compared to using structured code such as for loops and while loops.
When you look at a goto or a label, you don't really know where is goes to or comes from without reading or searching through the code for the label name. This is tricky especially if the goto doesn't fit on the same screen as the label. Compare this to a for loop or a while loop or an if.. you can tell from the structure (i.e. indenting of the code) what the execution path is.
Having said this, it sometimes is useful, especially for example when jumping out of some nested for loops that are digging for a particular value inside a multi-dimensional array. You could use a goto here to jump out of the for loops when the correct value is found.

Resources