v icon indicating copy to clipboard operation
v copied to clipboard

Undefined behavior if variable is out of scope when defer is called

Open kravlad opened this issue 7 months ago • 4 comments

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.

kravlad avatar Jun 06 '25 16:06 kravlad

Connected to Huly®: V_0.6-23022

huly-for-github[bot] avatar Jun 06 '25 16:06 huly-for-github[bot]

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

kravlad avatar Jun 07 '25 00:06 kravlad

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
}

felipensp avatar Jun 10 '25 11:06 felipensp

Since it is not a local scoped defer it uses a i variable not initialized... hence the output looks random.

felipensp avatar Jun 10 '25 11:06 felipensp