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

globals fields segfault (or write fault in os.zig) #19546

Closed
gh0st-work opened this issue Apr 5, 2024 · 3 comments
Closed

globals fields segfault (or write fault in os.zig) #19546

gh0st-work opened this issue Apr 5, 2024 · 3 comments
Labels
question No questions on the issue tracker, please.

Comments

@gh0st-work
Copy link

Zig Version

0.11.0 (x86_64-linux.3.16...5.10.81-gnu.2.19)

Steps to Reproduce and Observed Behavior

const std = @import("std");

pub const User = struct { name: []const u8 };
pub const user_john = User{ .name = "John" };
pub const user_richard = User{ .name = "Richard" };
pub const users_default: [2]User = .{ user_john, user_richard };

pub const Database = struct {
    users: []User,

    pub fn default() Database {
        var users = users_default;
        return Database{
            .users = &users,
        };
    }
};

pub const Service = struct {
    users: []User,

    pub fn init(db: Database) Service {
        return Service{
            .users = db.users,
        };
    }
};

test "fault" {
    std.debug.print("\n", .{});
    var db = Database.default();
    var service = Service.init(db);
    for (service.users) |user|
        std.debug.print("name:{s}\n", .{user.name});
}

This snippet code organization / structure causes some strange behavior: segfaults, os.write faults, misreading. In this example my output is:

Test [1/1] test.fault... 
name:John
name:thread 110 panic: reached unreachable code
/home/user/.zig/lib/std/os.zig:1133:23: 0x273c8f in write (test)
            .FAULT => unreachable,
                      ^
/home/user/.zig/lib/std/fs/file.zig:1163:28: 0x26089a in write (test)
            return os.write(self.handle, bytes);
                           ^
/home/user/.zig/lib/std/io/writer.zig:17:27: 0x22e208 in write (test)
            return writeFn(self.context, bytes);
                          ^
/home/user/.zig/lib/std/io/writer.zig:23:40: 0x225a60 in writeAll (test)
                index += try self.write(bytes[index..]);
                                       ^
/home/user/.zig/lib/std/fmt.zig:1047:28: 0x22eafa in formatBuf__anon_5235 (test)
        try writer.writeAll(buf);
                           ^
/home/user/.zig/lib/std/fmt.zig:656:45: 0x225dfe in formatType__anon_3696 (test)
                            return formatBuf(value, options, writer);
                                            ^
/home/user/.zig/lib/std/fmt.zig:184:23: 0x225d2d in format__anon_3649 (test)
        try formatType(
                      ^
/home/user/.zig/lib/std/io/writer.zig:28:34: 0x224de0 in print__anon_2843 (test)
            return std.fmt.format(self, format, args);
                                 ^
/home/user/.zig/lib/std/debug.zig:90:27: 0x22468c in print__anon_1105 (test)
    nosuspend stderr.print(fmt, args) catch return;
                          ^
/home/user/projects/proj-zig/bug.zig:34:24: 0x2244e5 in test.fault (test)
        std.debug.print("name:{s}\n", .{user.name});
                       ^
/home/user/.zig/lib/test_runner.zig:176:28: 0x22dc8e in mainTerminal (test)
        } else test_fn.func();
                           ^
/home/user/.zig/lib/test_runner.zig:36:28: 0x22576a in main (test)
        return mainTerminal();
                           ^
/home/user/.zig/lib/std/start.zig:564:22: 0x224ba2 in posixCallMainAndExit (test)
            root.main();
                     ^
/home/user/.zig/lib/std/start.zig:243:5: 0x2246f1 in _start (test)
    asm volatile (switch (native_arch) {
    ^
???:?:?: 0x0 in ??? (???)

Mb I'm stupid and don't know how to work with pointers to comptime data, if so, please explain

Expected Behavior

Run correctly

@gh0st-work gh0st-work added the bug Observed behavior contradicts documented or intended behavior label Apr 5, 2024
@Vexu
Copy link
Member

Vexu commented Apr 5, 2024

You are returning a pointer to a stack variable that is invalidated when the function returns.

    pub fn default() Database {
        var users = users_default;
        return Database{
            .users = &users,

Making users_defalt a var and returning a pointer to it makes the code run as expected.

@Vexu Vexu closed this as not planned Won't fix, can't repro, duplicate, stale Apr 5, 2024
@Vexu Vexu added question No questions on the issue tracker, please. and removed bug Observed behavior contradicts documented or intended behavior labels Apr 5, 2024
@gh0st-work
Copy link
Author

gh0st-work commented Apr 5, 2024

Thx for your explanations, but shouldn't it be somehow explained by the compiler? Why is it even legal saving somewhere pointer to stack? In C it is considered memory leak and C report it immediately (and LLVM/clang explains where exactly it's happened, mb with sanitizers, I don't quite remember).

@Inve1951
Copy link
Contributor

Inve1951 commented Apr 5, 2024

afaik making it illegal is a planned improvement
see #2301, #2646, #5725

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question No questions on the issue tracker, please.
Projects
None yet
Development

No branches or pull requests

3 participants