ID:2947412
 
Resolved
When catching exceptions in a catch block, the stack wasn't reset to the size before try, causing problems with certain situations like for() loops using the to keyword.
BYOND Version:515
Operating System:Windows 11 Pro
Web Browser:Firefox 131.0
Applies to:Dream Daemon
Status: Resolved (515.1644)

This issue has been resolved.
When using a for (var/i in 1 to 10) style loop, a try catch exception will break out of the loop early.

Using for (var/i, var < 10, i++) style loops do NOT exhibit this issue.


Below is the code snippets. I use wrench bot when testing code which compiles on 515.1643. ENC_OUT just takes the output and formats it sanely, and OUT is just a macro for world.log

This is the code that Wrench generates and then compiles:

#include "util.dm"
#if DM_VERSION >= 515
#pragma ignore loop_checks
#endif
/world/loop_checks = FALSE
/world/New()
main()
del(src)


/proc/a()
var/x = 0
var/tryvarcheck
for (var/y in 1 to 5)
ENC_OUT(x)
ENC_OUT(y)
try
tryvarcheck = y / x
ENC_OUT(tryvarcheck)
catch(var/exception/E)
OUT << "Except: [E]"
x += 1
return x
MAIN
ENC_OUT(a())


It will generate the following output:

x => 0
y => 1
Except: Division by zero
a() => 1



MEANWHILE, this style of loop will continue after the try-catch fires.

#include "util.dm"
#if DM_VERSION >= 515
#pragma ignore loop_checks
#endif
/world/loop_checks = FALSE
/world/New()
main()
del(src)


/proc/a()
var/x = 0
var/tryvarcheck
for (var/y, y < 5, y++)
ENC_OUT(x)
ENC_OUT(y)
try
tryvarcheck = y / x
ENC_OUT(tryvarcheck)
catch(var/exception/E)
OUT << "Except: [E]"
x += 1
return x
MAIN
ENC_OUT(a())


Output:

x => 0
y => null
tryvarcheck => 0
x => 1
y => 1
tryvarcheck => 1
x => 2
y => 2
tryvarcheck => 1
x => 3
y => 3
tryvarcheck => 1
x => 4
y => 4
tryvarcheck => 1
a() => 5
</10>
Can you provide a test case for this? Your snippet includes a separate file. Any snippet in a bug report should be completely self-contained if there isn't a test project to go with it.
Here's the full main.dm build within dream maker instead of through wrench the bot on 515.1461. This uses C++ style and will continue looping.

/*
These are simple defaults for your project.
*/


world
fps = 25 // 25 frames per second
icon_size = 32 // 32x32 icon size by default

view = 6 // show up to 6 tiles outward from center (13x13 view)


// Make objects move 8 pixels per tick when walking

mob
step_size = 8

obj
step_size = 8


/world/loop_checks = FALSE
/world/New()
main()
del(src)


/proc/a()
var/x = 0
var/y = 0
var/tryvarcheck
for (y, y < 5, y++)
world.log << "x is [x]"
world.log << "y is [y]"
try
tryvarcheck = y / x
world.log << "tryvarcheck is [tryvarcheck]"
catch(var/exception/E)
world.log << "Except: [E]"
x += 1
return x

/proc/main()
world.log << a()


x is 0
y is 0
Except: Division by zero
x is 1
y is 1
tryvarcheck is 1
x is 2
y is 2
tryvarcheck is 1
x is 3
y is 3
tryvarcheck is 1
x is 4
y is 4
tryvarcheck is 1
5



Here is the `in 1 to 5` style loop.

/*
These are simple defaults for your project.
*/


world
fps = 25 // 25 frames per second
icon_size = 32 // 32x32 icon size by default

view = 6 // show up to 6 tiles outward from center (13x13 view)


// Make objects move 8 pixels per tick when walking

mob
step_size = 8

obj
step_size = 8


/world/loop_checks = FALSE
/world/New()
main()
del(src)


/proc/a()
var/x = 0
var/y = 0
var/tryvarcheck
for (y in 1 to 5)
world.log << "x is [x]"
world.log << "y is [y]"
try
tryvarcheck = y / x
world.log << "tryvarcheck is [tryvarcheck]"
catch(var/exception/E)
world.log << "Except: [E]"
x += 1
return x

/proc/main()
world.log << a()


OUTPUT:

x is 0
y is 1
Except: Division by zero
1


As a result of this issue, this PR on github for shiptest had to be implemented:

https://github.com/shiptest-ss13/Shiptest/pull/1885
Lummox JR resolved issue with message:
When catching exceptions in a catch block, the stack wasn't reset to the size before try, causing problems with certain situations like for() loops using the to keyword.