ID:1301315
 
(See the best response by Jp.)
Code:
client
verb
test(n as num)
var/current = 0
for(var/i = 1, i<=n , i++)
world << "[i]"
for(var/x = 1,x<=n,x++)
for(var/y = 1,y<=n,y++)
current = get(x,y)
if(!current) CRASH("[x],[y]")


proc
get()
if(length(args)!=2) CRASH("wrong number of indices [length(args)]!=2")
return length(args)


Problem description:
When I run the code above with n = 100, I get an error when:

i = 7
x = 56
y = 35

Here is a the output of the error:
runtime error: wrong number of indicies 0!=2
proc name: get (/proc/get)
source file: ArgsTest.dm,15
usr: Asielen (/mob)
src: null
call stack:
get(56, 35)
Asielen (/client): test(100)
runtime error: 56,35
proc name: test (/client/verb/test)
source file: ArgsTest.dm,10
usr: Asielen (/mob)
src: Asielen (/client)
call stack:
Asielen (/client): test(100)


This was of course forced by CRASH however, CRASH() should not have been called at all. The error clearly shows that get() was called with two arguments but for some reason on those specific values, not all the arguments are passed.

This error only occurs once per runtime. Once it shows up once, it will not show up again until the program is restarted.

It will also show up for other values of n:

n = 500
i = 1
x = 132
y = 35

n = 1000
i = 1
x = 66
y = 535

but only once per runtime. If I get the error for n=100 it wont show up for n=1000 and vice versa.

Everytime I try it, it always crashes at the same values the first time it runs and then runs fine if I run it again (without restarting the program)

I must be missing something, this doesn't make any sense. Maybe I hit a recursion limit? But then why would it only throw an error once and not every time?

EDIT: New information, I have been testing this more. It seems it doesn't happen when doing a soft reboot of the program using Reboot() only when the program is fully closed and reopened.
I have done some more testing and this seems to be an issue with a built in limit,

When I do this:
client
verb
test()
var/current = 0
for(var/x = 1,x<=65534,x++)
for(var/y = 1,y<=1,y++)
current = get(x,y)
if(!current) CRASH("[x],[y]")


There are no errors ever.


However when I change it to:

client
verb
test()
var/current = 0
for(var/x = 1,x<=65535,x++)
for(var/y = 1,y<=1,y++)
current = get(x,y)
if(!current) CRASH("[x],[y]")


There is an error on the first run and then not again.


Is this a built in limit of ~65534 loops? If so then why does the error only happen on the first run of the proc and not every run?


EDIT:
This also occurs if the 65535 number is split between loops:
client
verb
test()
var/current = 0
for(var/x = 1,x<=65530,x++)
for(var/y = 1,y<=6,y++)
current = get(x,y)
if(!current) CRASH("[x],[y]")

I can confirm that the build in limit is the upper end of a 16(?) bit integer, so it's a lot more than that

Somewhere near 1.7 or 17 million I think?
Best response
That power of 2 is interesting. Not sure what BYOND would be storing per-loop that's getting screwed up. Perhaps the args list is allocated at proc call and then left for garbage collection to deallocate, and you're allocating them fast enough that you run out of args lists before garbage collection? I would suggest reporting a bug.

EDIT:
This crashes
client
verb
test()
var/current = 0
for(var/x = 1, x<= 65536, x++)
current = get(x,x)
if(!current) CRASH("[x],[x]")

proc
get(x, y)
if(length(args)!=2) CRASH("wrong number of indices [length(args)]!=2")
return 2//length(args)


This does not:
client
verb
test()
var/current = 0
for(var/x = 1, x<= 65536, x++)
current = get(x,x)
if(!current) CRASH("[x],[x]")

proc
get(x, y)
//if(length(args)!=2) CRASH("wrong number of indices [length(args)]!=2")
return 2//length(args)


That might lend some weight to the running-out-of-args-lists hypothesis. Is there some way you can avoid using the args list in the code you're triggering this with?