zig icon indicating copy to clipboard operation
zig copied to clipboard

Sentinel-terminated array `= undefined` makes sentinel uninitialized

Open Jonatanc05 opened this issue 1 year ago • 3 comments

Zig Version

0.12.0-dev.3533+e5d900268

Steps to Reproduce and Observed Behavior

I'm trying to use [32:0]u8 to interop with C. First, I'll show the code that worked for me:

    var sha256_1: [33]u8 = undefined;
    sha256_1[32] = 0x00;
    @breakpoint();

When the breakpoint is hit, memory at the address &sha256_1 obviously looks right:

aa aa aa aa aa aa aa aa  ªªªªªªªª
aa aa aa aa aa aa aa aa  ªªªªªªªª
aa aa aa aa aa aa aa aa  ªªªªªªªª
aa aa aa aa aa aa aa aa  ªªªªªªªª
00                       .

Now the code that I thought should work the same:

    var sha256_1: [32:0]u8 = undefined;
    @breakpoint();

but now memory is

aa aa aa aa aa aa aa aa  ªªªªªªªª
aa aa aa aa aa aa aa aa  ªªªªªªªª
aa aa aa aa aa aa aa aa  ªªªªªªªª
aa aa aa aa aa aa aa aa  ªªªªªªªª
aa                       ª

I'm on windows 11 btw

Expected Behavior

I would expect the sentinel to be initialized, just like I did manually in the first snippet. My intuition is that = undefined would not affect the sentinel. This might be a design decision but I haven't found any issue about it. I understand (guess) there might be efficiency reasons to this behaviour, maybe futurely we can include this in docs.

Jonatanc05 avatar May 10 '24 14:05 Jonatanc05

I’m not a Zig expert, so take this with a grain of salt.

My intuition is the opposite. If I initialize the variable to undefined I expect the entire memory region owned by the variable to be undefined. I don’t expect assigning undefined to set any bytes.

You should never read the variable before initializing it with a value and setting the sentinel correctly. If you read the variable before that, the behavior is undefined and so I don’t think it makes sense to complain about it not being null-terminated.

The one thing to check would be making sure that reading a null-terminated-typed-undefined variable has a reasonable error in debug mode.

MatthiasPortzel avatar May 16 '24 15:05 MatthiasPortzel

Initializing an array with this type of pattern is very common, and should not require manually setting the sentinel:

var array: [n:0]u32 = undefined;
for (&array, 0..) |*x, i| {
    x.* = @intCast(i);
}

silversquirl avatar May 16 '24 17:05 silversquirl

I still wish the semantics in my comment were correct, but I’ve been informed that I was mistaken about how sentinel-terminal-arrays actually work. (In particular, I expected operations on the array, like @silversquirl’s example, to use the sentinel to determine the length, when the compile-time length is used instead.)

MatthiasPortzel avatar May 16 '24 19:05 MatthiasPortzel