Undefined behavior if variable is out of scope when defer is called
Describe the bug
if we define a defer block inside the loop with a variable that is in local scope we get undefined behavior when defer is being called.
Reproduction Steps
fn main() {
for i in 1..4 {
defer {
println('Deferred execution for $i')
}
println('Hello, World! $i')
}
}
Expected Behavior
compile error?? (I don't know)
Current Behavior
output:
Hello, World! 1
Hello, World! 2
Hello, World! 3
Deferred execution for 49598448
Possible Solution
No response
Additional Information/Context
No response
V version
0.4.10 a91e2def83051b5ad177f89e058f4a09e79433ee
Environment details (OS name and version, etc.)
| V full version | V 0.4.10 a91e2def83051b5ad177f89e058f4a09e79433ee |
|---|---|
| OS | macos, macOS, 15.5, 24F74 |
| Processor | 8 cpus, 64bit, little endian, Apple M1 |
| Memory | 0.3GB/16GB |
| V executable | /Users/user/dev/v/v |
| V last modified time | 2025-06-05 15:14:14 |
| V home dir | OK, value: /Users/user/dev/v |
| VMODULES | OK, value: /Users/user/.vmodules |
| VTMP | OK, value: /tmp/v_501 |
| Current working dir | OK, value: /Users/user |
| Git version | git version 2.49.0 |
| V git status | weekly.2025.14-315-ga91e2def |
| .git/config present | true |
| cc version | Apple clang version 17.0.0 (clang-1700.0.13.5) |
| gcc version | Apple clang version 17.0.0 (clang-1700.0.13.5) |
| clang version | Apple clang version 17.0.0 (clang-1700.0.13.5) |
| tcc version | tcc version 0.9.28rc 2024-02-05 HEAD@105d70f7 (AArch64 Darwin) |
| tcc git status | thirdparty-macos-arm64 e447816c |
| emcc version | N/A |
| glibc version | N/A |
[!NOTE] You can use the 👍 reaction to increase the issue's priority for developers.
Please note that only the 👍 reaction to the issue itself counts as a vote. Other reactions and those to comments will not be taken into account.
Connected to Huly®: V_0.6-23022
For example, how it works in Go:
func main() {
for i := range 3 {
defer fmt.Println("Deferred execution for ", i)
fmt.Println("Hello, World! ", i)
}
}
output:
Hello, World! 0
Hello, World! 1
Hello, World! 2
Deferred execution for 2
Deferred execution for 1
Deferred execution for 0
VV_LOC void main__main(void) {
bool main__main_defer_0 = false;
int_literal i;
for (int i = 1; i < 4; ++i) {
main__main_defer_0 = true;
println(str_intp(2, _MOV((StrIntpData[]){{_S("Hello, World! "), 0xfe07, {.d_i32 = i}}, {_SLIT0, 0, { .d_c = 0 }}})));
}
// Defer begin
if (main__main_defer_0) {
println(str_intp(2, _MOV((StrIntpData[]){{_S("Deferred execution for "), 0xfe07, {.d_i32 = i}}, {_SLIT0, 0, { .d_c = 0 }}})));
}
// Defer end
}
Since it is not a local scoped defer it uses a i variable not initialized... hence the output looks random.