Is it safe to return pointers to local zero-size values?

Is the following code good?

const std = @import("std");

const T = struct{
    fn bar(_: *T) void {}
};

fn Foo() *T {
    var t = T{};
    return &t; // safe or not?
}

pub fn main() !void {
    const t = Foo();
    t.bar();
}

The pointer is dangling, but derefences will probably get optimized away (?) so it doesn’t matter.

I wouldn’t call it “good” in any case :sweat_smile:

1 Like

There’s no state you need here anyway, so you can just write:

const std = @import("std");

const T = struct{
    fn bar() void {}
};

pub fn main() !void {
    T.bar();
}

(Might not be the exact point here, but yeah)

Also, &.{} is acceptable for an empty struct/slice constant (but note that it’s been replaced in the stdlib wiith .empty semantics). But if you just need namespacing, use the above example.

1 Like

Well, there are no dereferences in the first place, only pointer copies, so I guess the code is technically fine… But I don’t really understand the utility of doing this. Should @zigo add any fields to the struct in the future and use them, a lot of code may become invalid and possibly hard to debug.

3 Likes

Looks like a good use case for making the return pointer an optional.

Sometimes, 3rd-party lib APIs need a anytype argument which is required to be a pointer.

For this use case, I think it is much better to pass &@as(T, .{}) in directly

Is the value of &@as(T, .{}) still valid after the caller function exits?

Every time when passing parameters, using this expression directly is logically equivalent to always creating a new empty structure, without the need to pass this reference elsewhere.

Why do you want to do this? Your previous replies haven’t really clarified this.

Some 3rd-party lib APIs might need a anytype argument which is required to be a pointer. And I don’t want to use allocators or global variables.

Yes, it’s safe. Pointers to empty structs always point to the same address. Derefencing it is a no-op.
But, as has been mentioned, it’s a footgun, as if you later add a field to it, you’re going to have undefined behaviour which could be hard to find.

3 Likes