[Closed] Recursive Function Crash
I remember reading somewhere about issues with recursive functions in old Max versions. However, while working on a recursive function I came across with a weird issue and I am not sure if this is a bug, a limitation of Maxscript or simply something I am doing wrong.
The following functions are useless and only meant to be used as test cases. Both of this functions crashes Max 2011 and newer versions every single time. Sometimes I get the alert box “An error occurred and max will quit.” and other times Max simply quits.
The amount of recursions is very low and it doesn’t seems to be the heap, so I am not sure where to look for.
(
delete objects
node = converttomesh (geosphere segs:7)
fn test &arr vert =
(
if vert > 0 do
(
append arr (getvert node vert)
test &arr (vert-1)
)
)
arr = #()
test &arr node.numverts
)
This very simple function also crashes Max.
(
fn test v =
(
if v > 0 do n = test (v-1)
)
test 500
)
I think that this will not help but,
Using this:
(
fn test v =
(
if v > 0 do
(
print (v-1)
n = test (v-1)
)
)
test 500
)
and MAx crashes when the 97 is printed in the listener
test 402 works with no problems
test 403 not works.
The geosphere created by your code have 492 vertices.
402 are the total amount of recursions that can be done or…???
I get different results in different Max versions. The limit of recursions I get are as follow.
3ds Max 2011 380 recursions
3ds Max 2012 380 recursions
3ds Max 2014 400 recursions
3ds Max 2015 400 recursions
If this is consistent across other systems/setups, then using recursive functions doesn’t seem to be a good idea at all as a 400 iterations limit is not a promising number.
If this is a bug, it is surprising that it was never fixed, not even in Max 2015. Weird.
yes… there is a limited number of nested recursions in max sdk. there is no way to change it.
i don’t know this number. it’s not really the number. it depends on how much the system(max) can allocate memory (it’s not mxs memory). so… just know that there is a limit
Perhaps the slight variations are due to differences in memory resources available for allocation on each user’s machine?
theres a memory limit on all recursive function regardless of programing language, every new recursion requires a new stack frame with all subsequent memory allocation for local variables.
in c/c++ this wouldn’t end very well getting to 500 recursions
void rec()
{
int arr[1000000];
if(condition != true)
rec();
}
If this is consistent across other systems/setups, then using recursive functions doesn’t seem to be a good idea at all as a 400 iterations limit is not a promising number.
recursion is always a trade off between the elegant solution and memory usage and as a every mxs function derives from value there probably lot of addition overhead to have to deal with and not knowing what the callers local stack frame will be they probably err on the side of caution.
Thank you all guys.
I understand that recursions can be potentially “dangerous” and can cause a huge overhead in any programing language. What surprised me is that the example I posed, which is minimal, causes a crash.
As far as these tests, MaxScript can’t handle 400 recursions of a single integer addition, which is a very low boundary, and with the amount of data we manage today you can reach it pretty quick.
I was also thinking it would be a good reference for others developers experiencing the same problem, as if you have a complex long recursive function, it might well take you a while to debug it and find the source of the problem.
Now, knowing that for a single integer addition the limit is 400 iterations, I think I’ll never use a recursive function unless I am 100% sure the user will never reach that limit. Although I try to test all code in the most demanding scenarios, this recursion limit is something I would have never expected.
Honestly, I thought it was more related to a bug in the internal mechanic that determines if you have entered in an infinite loop rather than a memory limit. Even though I do not understand why the crash and not an exception.
No threshold to manage this, no mention of this anywhere in the documentation, no exception thrown, can’t handle 400 integers? Definitely a bug or a very poor implementation of whatever it is.
My Conclusion:
If you are planning to use a recursive function to make your code shorter and as much as 25% faster (as stated in the MaxScript Help), be aware that it will probably cause you more troubles than benefits.
My Conclusion:
If you are planning to use a recursive function to make your code shorter and as much as 25% faster (as stated in the MaxScript Help), be aware that it will probably cause you more troubles than benefits.
really ? recursive depth of quicksort approximates to log2(n) so that would be 2^500 elements before the recursion broke max I suggest something else would break first :). I think any routine that required even half that kind of depth is a poor candidate for recursion.
Of course, I agree with you that something would break Max before that, but I think we are talking about different things.
I am refering to “recursive functions” in the context of this thread, specifically speaking about custom MaxScript recursive functions. I am excluding build-in functions, C#, Python, C++, etc.
[Recursive functions can be faster]( http://docs.autodesk.com/3DSMAX/15/ENU/MAXScript-Help/files/GUID-046BA8F9-DE6C-475F-8641-7F9A5952FF0B.htm)
I would be more than happy if a custom recursive MaxScript function would handle 2^50, but it doesn't seem to even handle 2^9.
getAnimatedProps is a nice example as a balanced tree enumeration is a good candidate for recursion, you would again be collecting in the order 2^500 animated props by the time you were close to breaking max’s recursion limit with it. Linear enumerations & unbalanced trees can be bad candidates for recursion.
I am refering to “recursive functions” in the context of this thread, specifically speaking about custom MaxScript recursive functions. I am excluding build-in functions, C#, Python, C++, etc.
if you implemented a recursive quicksort in maxscript it would still require on average 2^500 items for the recursion depth to reach 500.
So do you know why this very simple function breaks Max?
(
delete objects
node = converttomesh (geosphere segs:7)
fn test &arr vert =
(
if vert > 0 do
(
append arr (getvert node vert)
test &arr (vert-1)
)
)
arr = #()
test &arr node.numverts
)
Is it because it is bad implemented, lack of some sort of memory somewhere, a bug, a limit in the amount of consecutive recursions?
it just a pointless linear recursion e.g recursion depth = number of verts forcing max to exceed the mxs stack allocation. It’s a very poor candidate for recursion and it would break all programming languages in the end