Accidental Infinite Recursion

BlitzMax Forums/BlitzMax Programming/Accidental Infinite Recursion

DavidDC(Posted 2009) [#1]
I came across an interesting bug yesterday that I'd thought I'd share and check that my new 1.33rc5 build is doing what it should be doing.

When typing in a function argument, I accidentally entered type "String" instead of type "Int" for what I was going to use as a boolean. The result was an always true "boolean" argument, and an infinite self-call recursion loop.

What concerned me was that this bug sidestepped all my logging routines and gave me no clue where in the code it was occurring. Since my code base is over 500 K lines, it was a tad worrying.

Despite my try/catch block, the app in debug mode just dropped out with no errors with a

Process complete


Obviously infinite recursion is going to break your code. But is there any way it can throw some kind of exception when it does?

SuperStrict

' Oops I typed "String" here!
Function AccidentalRecursion(_count:Int, _b_recurse:String = False)
		
	Print _count

	If _b_recurse
		AccidentalRecursion(_count+1)
	EndIf
	
End Function

Try
	AccidentalRecursion(0)
						
	Catch exception:Object
		Print exception.ToString()
		
End Try


Running this on my machine (XP) gives
..
149297
149298
149299

Process complete



Brucey(Posted 2009) [#2]
On Mac, the crash report should show you there's a recursion problem (is so much as there'll be a list of function calls about 512 deep) - although it won't help you to see where it is.


DavidDC(Posted 2009) [#3]

On Mac, the crash report should show you there's a recursion problem


Alas, most of my users will be on XP/Vista.


N(Posted 2009) [#4]
Make sure to read what you write twice at least, then? There isn't really any other option in BMax short of making sure to have useful debug output, common sense, and so on.


DavidDC(Posted 2009) [#5]
Make sure to read what you write twice at least, then?

Sure, but mistyping an argument isn't the only way to invoke infinite recursion. I'm sure it would be possible to come up with some hairy user-install specific instances where such a bug could arise.

I guess my point is - it is dropping back to the IDE "somehow". It'd be nice if that "somehow" wasn't silent.


Gabriel(Posted 2009) [#6]
I'm not sure what you hope for it to do. It isn't failing to report an error as such. You're literally crashing the debugger. Every time you call a new function without returning from the old one, you're adding another set of data to the stack. If you do that often enough without returning, you'll eventually run out of stack space. If you run out of stack space, the debugger will crash. I *suppose* the debugger could track the stack space and report that it's run out, but even then it doesn't automatically mean infinite recursion. You can actually run out of stack space even with a legitimate program if your recursion goes deep enough. Essentially, if you crash the debugger, there's a good chance you ran out of stack space.


N(Posted 2009) [#7]
I'm sure it would be possible to come up with some hairy user-install specific instances where such a bug could arise.
Come up with one. I don't think you're going to find an instance where the problem really comes about because of a user's setup.


DavidDC(Posted 2009) [#8]
Well my concern wasn't so much for when it happens to me in debugmode in front of my IDE. It is if it happens to a user rarely and intermittently and all they have to tell me is "the app just vanishes".

I have built the ability to log function and method entry/exit into 90+% of my code. But this log trace doesn't write to file in such a case. And I can't really have them run full log trace mode, where every entry exit is recorded to file, because the slow down would make the app unwieldy - especially since it could be hours/days/weeks before the bugs shows for them again.

When I asked the question, I was concerned my 1.33rc5 build might not have gone right - but if this is expected behaviour on XP then I'll just have to write better code / construct more thorough tests :-)

Come up with one?

Oh I don’t know – how about when the stars align with this kind of setup:
Function A
	
	If Condition B Call Function B

Function B

	If Condition C Call Function C

..

Function N 

	If Condition N Call Function A



N(Posted 2009) [#9]
Oh I don’t know – how about when the stars align with this kind of setup:
That's not a user-specific instance, or even an example...

I'll be frank here: you are not going to find a situation where you recurse infinitely without it being your fault and only your fault. For that reason, you need to take care that when you write code, you review it and make sure you wrote it correctly. Then review it again. If it's recursive, make sure your base case works and that you're handling each step into the recursion properly. That's all you'll get in BlitzMax, and that's all you can hope to get in most any programming language.


Nate the Great(Posted 2009) [#10]
if you are attemting a scripting language then it can certainly be the user's fault but other than that, I don't see why create all these whatifs.. just write neat code, deal with little bugs, and run in superstrict which has caught many bugs that may cause infinite recursion in my own code. were I have something like this

Graphics 640,480,0,60

Global ext:Int = False

While Not ext
Cls

If KeyDown(key_escape) Then a

Flip
Wend


Function a()
	
	If ext = False Then
		ex = True			'typo here
		b
	EndIf

End Function

Function b()
	Delay 100
	a
End Function


so if you superstrict the code above then it will catch the possible infinite recursion. but if you run as is, the infinite recursion happens as a result of a bug... so if you want to be safe then just make sure you have a function tree drawn out making sure functions higher on the tree don't call functions at the beginning of the tree