Open andrewrk opened 5 years ago
I may have run into this bug, and got some surprising behavior.
const std = @import("std");
const Point = struct {
x: u32,
y: u32,
};
fn print_point(point: Point) void {
std.debug.warn("Point (0x{x}, 0x{x})\n", .{ point.x, point.y });
}
pub fn main() void {
var my_point: Point = Point{ .x = undefined, .y = 5 };
print_point(my_point);
my_point = Point{ .x = undefined, .y = 5 };
print_point(my_point);
}
Here's the output on my machine:
$ zig run test.zig
Point (0x0, 0x5)
Point (0xaaaaaaaa, 0x5)
I asked on Discord, and it was suggested that this was related to this bug, and that in the variable declaration, my_point
is loaded from a global, but in the assignment it was loaded from immediates.
I'm not sure what the difference is, but I'm adding the example in case it's useful.
There may need to be an exception when the size of the global is larger than some amount such as 4 KiB, to avoid bloating binary size.
One way to do this is to put such variables in a special section, and then before main() memset the entire section to 0xaa. This would possibly require modifications to the default linker script.
Putting uninitialized globals in a custom linker section would also enable us to make a valgrind client request before main, after the memset to 0xaa. This would give Zig binaries a feature that C binaries don't have: valgrind able to detect uninitialized globals.
This would not be available if the user did
export fn main
and linked libc. But it would be available if they linked libc and usedpub fn main
.