Closed iamfraggle closed 2 years ago
Just thought to try the following which also fails:
var include = self.marked[y][x];
if (!include) unmarked += cell;
I appear to have omitted a comment I intended to put in the code. The issue only triggers if Board has been created via Board.construct()
. Instantiating Board manually bypasses the problem.
There seems to be something strange going on, but I believe you're invoking undefined behavior.
In Board.construct
you are doing:
var out: Board = undefined;
which can skip setting the default values for the marked
and complete
fields (the entire struct just gets initialized with 'undefined' memory). In Debug mode, this doesn't seem to happen (they appear to be set to false if you print them), but if you run the code in ReleaseFast and add std.debug.print("{}\n", .{out});
after the var out: Board = undefined
line you get a mishmash of random values.
I think what might be happening is that there is some Debug-specific optimizations that are happening because the compiler knows that marked
is undefined
, and somehow the if (!self.marked[y][x])
is triggering that.
It's possible to verify this by running with Valgrind:
zig test 10479.zig -femit-bin 10479 --test-no-exec
valgrind ./10479 zig
...
==4113839== Conditional jump or move depends on uninitialised value(s)
==4113839== at 0x208CFD: Board.mark (10479.zig:32)
==4113839== by 0x207E0A: test "example test" (10479.zig:109)
==4113839== by 0x231DE7: std.special.main (test_runner.zig:77)
==4113839== by 0x22A44C: std.start.callMain (start.zig:543)
==4113839== by 0x20ACEE: std.start.initEventLoopAndCallMain (start.zig:495)
==4113839== by 0x20ACEE: std.start.callMainWithArgs (start.zig:445)
==4113839== by 0x209626: std.start.posixCallMainAndExit (start.zig:409)
==4113839== by 0x209432: _start (start.zig:322)
==4113839== by 0x1: ???
==4113839== by 0x1FFEFFFFD6: ???
==4113839== by 0x1FFEFFFFDE: ???
...
(and the same error triggered by lines 40, 47, and 66)
The fix for your code would be to do:
var out: Board = .{ .grid = undefined };
thereby only setting the grid
field to undefined, and allowing the rest of the fields to use their defaults.
Not sure about what (if anything?) should be done on the compiler's end.
EDIT: This seems to be the relevant proposal: https://github.com/ziglang/zig/issues/211
Thanks for the explanation!
Zig Version
0.9.0
Steps to Reproduce
zig init-exe
Set src/main.zig to the code belowzig build test
Expected Behavior
Test [0/1] test "example test"... 1/1 test "example test"... OK
Actual Behavior
Test [0/1] test "example test"... 1/1 test "example test"... expected 0, found 4512
Any code guarded by the offending
if (!<expression)
does not get executed. Note that onlyif (!<expression)
is affectedif (<expression>)
in the same scenario works correctly.