Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Array/slice of undefined length compiles incorrectly #21915

Open
buzmeg opened this issue Nov 5, 2024 · 5 comments
Open

Array/slice of undefined length compiles incorrectly #21915

buzmeg opened this issue Nov 5, 2024 · 5 comments
Labels
bug Observed behavior contradicts documented or intended behavior

Comments

@buzmeg
Copy link

buzmeg commented Nov 5, 2024

Zig Version

0.14.0-dev.2126+e27b4647d

Steps to Reproduce and Observed Behavior

The following code compiles and then segfaults when run

pub fn main() void {
    var aa: []u32 = undefined;
    aa[1] = 1;

    if (aa[1] == 2) {
        @panic("Bleah.");
    }
}

This is quite surprising. I fully expected the code to fail to compile with an error along the lines of "Cannot infer length".

Can confirm that Zig 0.13.0 on godbolt exhibits same behavior.

Expected Behavior

Code should fail to compile with an error.

@buzmeg buzmeg added the bug Observed behavior contradicts documented or intended behavior label Nov 5, 2024
@nektro
Copy link
Contributor

nektro commented Nov 5, 2024

not a bug, this is a slice which setting it to undefined makes it have an undefined pointer and undefined length. writing to undefined memory causes a segfault.

@jrfondren
Copy link

The error you expected would come from this code:

test {
    var aa: [_]32 = undefined;
    aa[1] = 1;
}

@buzmeg
Copy link
Author

buzmeg commented Nov 5, 2024

@nektro Then why didn't I get a runtime check failure instead of a segfault? I'm not compiling in ReleaseFast?

This comes up a lot in Vulkan where you pass an array to be filled in:

        var aa: [MAX_LENGTH]u32 = undefined;
        const num_entries = fill_the_array(&aa);

The bug was that I accidentally deleted MAX_LENGTH while editing. I fully expected Zig to bark at me somehow.

Fortunately, I made this typo right after I committed, so a quick diff pulled this up quite easily.

Had this been right after a set of changes which were about to get committed, it would have taken me a rather significant chunk of time to track down.

@Rexicon226
Copy link
Contributor

Then why didn't I get a runtime check failure instead of a segfault? I'm not compiling in ReleaseFast?

There's no checking for undefined at runtime, it's not a defined state that a value can have. It's, for lack of a better word, undefined. See #211 for more information.

The bug was that I accidentally deleted MAX_LENGTH while editing. I fully expected Zig to bark at me somehow.

If you were to delete MAX_LENGTH and be left with a

var aa: []u32 = undefined;

the type would drastically change and there's no way fill_the_array would have accepted it.

@buzmeg
Copy link
Author

buzmeg commented Nov 5, 2024

Vulkan is taking something that generally elides to void* at bottom so it slides through.

See: vkEnumeratePhysicalDevices, for example: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkEnumeratePhysicalDevices.html

VkPhysicalDevice is VK_DEFINE_HANDLE(VkPhysicalDevice) which winds up eliding to void*.

Thanks for the pointer as to why undefined can't be detected at runtime.

I'll probably have to start initializing all my arrays to avoid this. It's probably a better idea than using undefined, anyway, if the code isn't performance sensitive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior
Projects
None yet
Development

No branches or pull requests

4 participants