zig.guide
zig.guide copied to clipboard
Referencing stack memory and a @frame pointer before suspending
Hey @Sobeston thanks for ziglearn! It's been a huge help learning Zig.
Just an idea to add to the Async section:
Normally, passing a pointer to a struct allocated on the stack to another function somewhere else is verboten because it's UB (the stack memory disappears and becomes undefined once the function returns).
However, with suspend
, it seems like a common pattern is to do exactly this, with a struct allocated on the stack including some data as well as the @frame
pointer, and then passing the @ptrToInt
of the pointer to this struct somewhere else, e.g. as the user data when submitting an io_uring sqe.
Here are two real world examples from @kprotty and @daurnimator:
https://gist.github.com/kprotty/c01630ae285e8b14cb7a36c454ac2d87#file-uring_async-zig-L101-L102 https://gist.github.com/daurnimator/699320cda828303671a21d15bb4a3753#file-uring-nonblock-fifo-async-zig-L128-L140
I guess this is obvious to people (and really easy!), but for me as a newcomer this was not something I would have thought of because I don't really understand what happens to the async stack after the suspend
, and because usually it's not safe to take a pointer to stack memory.
It would be great to see an example of this in the Async section for ziglearn, an explanation that it's safe, and why it works in the case of suspend
, showing how suspend
keeps the async frame and its stack allocated variables safe... just so people can get going with suspend
quicker (assuming they need to) without worrying that they need to do heap allocation.
Normally, passing a pointer to a struct allocated on the stack to another function somewhere else is verboten because it's UB (the stack memory disappears and becomes undefined once the function returns).
Not exactly.
Something like this is entirely valid and normal:
fn foo() void {
var buf: [100]u8 = undefined;
bar(&buf);
}
The key thing is not return
-ing a pointer to stack memory (or allowing the stack pointer out into the world for longer than after you return
).
And suspend
is not return
.
The key thing is not return-ing a pointer to stack memory (or allowing the stack pointer out into the world for longer than after you return).
Yes, thanks for clarifying, that was the UB I had in mind (the stack memory disappears and becomes undefined once the function returns).