# Segmentation fault after flushing to stdout

**URL:** <https://ziggit.dev/t/segmentation-fault-after-flushing-to-stdout/16799>\
**Category:** Help\
**Tags:** standard-library\
**Created:** [July 20, 2026, 9:29am UTC](https://ziggit.dev/t/segmentation-fault-after-flushing-to-stdout/16799 "2026-07-20T09:29:16Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![o-wrobel](https://ziggit.dev/letter_avatar_proxy/v4/letter/o/ecc23a/32.png) [@o-wrobel](https://ziggit.dev/u/o-wrobel)\
**Post date:** [July 20, 2026, 9:29am UTC](https://ziggit.dev/t/segmentation-fault-after-flushing-to-stdout/16799/1 "2026-07-20T09:29:16Z")

</div>

I’m trying to use the Writer.print function, but upon flushing I get this segfault:

```plaintext
Segmentation fault at address 0x79
/nix/store/d0kkd93aji32klh4npp5fzq82lb84p85-zig-0.16.0/lib/zig/std/Io.zig:453:29: 0x1039fb3 in operate (std.zig)
return io.vtable.operate(io.userdata, operation);
^
/nix/store/d0kkd93aji32klh4npp5fzq82lb84p85-zig-0.16.0/lib/zig/std/Io/File.zig:614:27: 0x11df519 in writeStreaming (std.zig)
return (try io.operate(.{ .file_write_streaming = .{
^
/nix/store/d0kkd93aji32klh4npp5fzq82lb84p85-zig-0.16.0/lib/zig/std/Io/File/Writer.zig:126:36: 0x11defb6 in drainStreaming (std.zig)
const n = w.file.writeStreaming(io, header, data, splat) catch |err| {
^
/nix/store/d0kkd93aji32klh4npp5fzq82lb84p85-zig-0.16.0/lib/zig/std/Io/File/Writer.zig:93:63: 0x11de9cc in drain (std.zig)
.streaming, .streaming_simple => return drainStreaming(w, data, splat),
^
/nix/store/d0kkd93aji32klh4npp5fzq82lb84p85-zig-0.16.0/lib/zig/std/Io/Writer.zig:319:39: 0x1036a32 in defaultFlush (std.zig)
while (w.end != 0) _ = try drainFn(w, &.{“”}, 1);
^
/nix/store/d0kkd93aji32klh4npp5fzq82lb84p85-zig-0.16.0/lib/zig/std/Io/Writer.zig:313:26: 0x112bb93 in flush (std.zig)
return w.vtable.flush(w);
^
/home/oskar/Dev/raytracing-zig/src/main.zig:10:21: 0x11d7434 in main (main.zig)
try writer.flush();
^
/nix/store/d0kkd93aji32klh4npp5fzq82lb84p85-zig-0.16.0/lib/zig/std/start.zig:737:30: 0x11d7eee in callMain (std.zig)
return wrapMain(root.main(.{
^
/nix/store/d0kkd93aji32klh4npp5fzq82lb84p85-zig-0.16.0/lib/zig/std/start.zig:190:5: 0x11d7201 in _start (std.zig)
asm volatile (switch (native_arch) {
^
run
└─ run exe raytracing_zig failure
error: process terminated with signal ABRT
failed command: /home/oskar/Dev/raytracing-zig/zig-out/bin/raytracing_zig

Build Summary: 3/5 steps succeeded (1 failed)
run transitive failure
└─ run exe raytracing_zig failure

```

My program looks like this:

```zig
const std = @import(“std”);

pub fn main(init: std.process.Init) !void {
const io = init.io;

var buf: [50]u8 = undefined;
const stdout = std.Io.File.stdout().writer(io, &buf);
var writer = stdout.interface;
try writer.print("hi {}", .{2});
try writer.flush();
}

```

Previously I used writeStreamingAll, which worked fine, but I needed a function that also formatted.  
I’d be really grateful for any help regarding this error

---

<div class="post-metadata">

**Author:** ![schlyngel](https://ziggit.dev/user_avatar/ziggit.dev/schlyngel/32/9552_2.png) [@schlyngel](https://ziggit.dev/u/schlyngel)\
**Post date:** [July 20, 2026, 9:32am UTC](https://ziggit.dev/t/segmentation-fault-after-flushing-to-stdout/16799/2 "2026-07-20T09:32:26Z")

</div>

Not sure if this fixes your Error but it should be `const writer = &stdout.interface;`  
Otherwise your are copying the interface i think.

---

<div class="post-metadata">

**Author:** ![truly-not-taken](https://ziggit.dev/user_avatar/ziggit.dev/truly-not-taken/32/6205_2.png) [@truly-not-taken](https://ziggit.dev/u/truly-not-taken)\
**Post date:** [July 20, 2026, 12:17pm UTC](https://ziggit.dev/t/segmentation-fault-after-flushing-to-stdout/16799/3 "2026-07-20T12:17:42Z")

</div>

> [@schlyngel](#):
>
> it should be `var writer =`

`const` actually

---

<div class="post-metadata">

**Author:** ![mkrieger1](https://ziggit.dev/user_avatar/ziggit.dev/mkrieger1/32/2109_2.png) [@mkrieger1](https://ziggit.dev/u/mkrieger1)\
**Post date:** [September 1, 2026, 7:46am UTC](https://ziggit.dev/t/segmentation-fault-after-flushing-to-stdout/16799/4 "2026-09-01T07:46:11Z")

</div>

I got bitten by the same mistake.

I have two questions:

1. Can someone please explain why using a copy of `stdout.interface` makes a difference to using a reference to `stdout.interface`? Even if it is a copy, shouldn’t it be a shallow copy, and any copied internal references should still point to the original valid memory locations?

2. This is what I would consider a footgun: the code compiles and maybe appears to work (doesn’t crash when omitting `writer.flush`), but then crashes. It also violates what I recall (or maybe just imagine) being one of the Zig philosophies: the simplest way should be the correct way (using `stdout.interface` is simpler than `&stdout.interface`). Is there a way to write this code such that the incorrect way is a compile error?

---

<div class="post-metadata">

**Author:** ![mkrieger1](https://ziggit.dev/user_avatar/ziggit.dev/mkrieger1/32/2109_2.png) [@mkrieger1](https://ziggit.dev/u/mkrieger1)\
**Post date:** [September 1, 2026, 8:00am UTC](https://ziggit.dev/t/segmentation-fault-after-flushing-to-stdout/16799/5 "2026-09-01T08:00:27Z")

</div>

Maybe I also have to revisit my understanding of the fundamentals of the Zig language…

This code works fine:

```zig
var stdout = std.Io.File.stdout().writer(io, &buf);
try stdout.interface.print("hi {}\n", .{2});
try stdout.interface.flush();

```

and to my understanding so far, this should be exactly equivalent to factoring out the expression `stdout.interface` (and giving it the name `writer`):

```zig
var stdout = std.Io.File.stdout().writer(io, &buf);
const writer = stdout.interface;
try writer.print("hi {}\n", .{2});
try writer.flush();

```

but this doesn’t compile:

```zig
seg.zig:7:9: error: local variable is never mutated
    var stdout = std.Io.File.stdout().writer(io, &buf);
        ^ ~~~~~
seg.zig:7:9: note: consider using 'const'
seg.zig:9:15: error: expected type '*Io.Writer', found '*const Io.Writer'
    try writer.print("hi {}\n", .{2});
        ~~~~~~^~~~~~
seg.zig:9:15: note: cast discards const qualifier

```

So maybe the compiler _does_ try to nudge me in the correct direction, but instead of shuffling around `const` and `var` until it compiles, I didn’t see that I needed to add `&`.

---

<div class="post-metadata">

**Author:** ![vulpesx](https://ziggit.dev/user_avatar/ziggit.dev/vulpesx/32/3989_2.png) [@vulpesx](https://ziggit.dev/u/vulpesx)\
**Post date:** [September 1, 2026, 8:07am UTC](https://ziggit.dev/t/segmentation-fault-after-flushing-to-stdout/16799/6 "2026-09-01T08:07:48Z")

</div>

> [@mkrieger1](#):
>
> Can someone please explain why using a copy of `stdout.interface` makes a difference to using a reference to `stdout.interface`? Even if it is a copy, shouldn’t it be a shallow copy, and any copied internal references should still point to the original valid memory locations?

The data being copied is this

```zig
vtable: *const VTable,
buffer: []u8,
end: usize = 0,

```

Notice how there is _not_ a pointer to implementation state.  
Instead, implementations use `@fieldParentPtr` to convert a `*Reader`/`*Writer`, which is **assumed** to be a pointer to a field (you specify by name) in the implementation type.

By making, and using, a copy of the `Reader`/`Writer` field, you are breaking that assumption. But that assumption is currently can’t be verified, so the code just continues assuming it is correct, and treating the memory around the copy as though it is the implementation type when it is not, this is illegal behaviour, anything could happen e.g. operating on a different file you opened in an entirely different part of your program!!!.

I say “currently” specifically because there are [plans to make it checked](https://github.com/ziglang/zig/issues/2414)

> [@mkrieger1](#):
>
> This is what I would consider a footgun: the code compiles and maybe appears to work (doesn’t crash when omitting `writer.flush`), but then crashes. It also violates what I recall (or maybe just imagine) being one of the Zig philosophies: the simplest way should be the correct way (using `stdout.interface` is simpler than `&stdout.interface`). Is there a way to write this code such that the incorrect way is a compile error?

Sure, but they require language changes in one of the following directions

- a generic/trait/etc system that makes this a non issue
- pinned types, have issues with zigs existing type system and memory model
- pinned places, solves issues of pinned types, but has a pretty damning issue that I can’t remember atm.
- borrow checker/lifetimes, drastically increases language and compiler complexity, slows compile times, false positives restrict possible code, false negatives defeat the point unless it is good enough.
- other things I can’t think of.

I am infavour of changing the language to make this a compile error, but I dont have a solution to actually do that without contradicting zigs ideals.

> [@mkrieger1](#):
>
> So maybe the compiler _does_ try to nudge me in the correct direction, but instead of shuffling around `const` and `var` until it compiles, I didn’t see that I needed to add `&`.

The compile error is specifically about incorrect `const` because the `Reader`/`Writer` data needs to be mutated, whether it’s a copy or not; you need a `var` regardless, and with it, you get the unchecked illegal behaviour I described earlier.
