Hi everyone! I’m encountering some issues while using the writer in the C++ bridge. Here’s the demo code:
- build.zig
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const mod = b.addModule("demo", .{
.root_source_file = b.path("src/glue.zig"),
.target = target,
.link_libc = true,
.link_libcpp = true,
});
mod.addCSourceFile(.{
.file = b.path("src/glue.cpp"),
.flags = &.{},
.language = .cpp,
});
const lib = b.addLibrary(.{
.name = "glue",
.root_module = mod,
});
const exe = b.addExecutable(.{
.name = "demo",
.root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.imports = &.{},
}),
});
exe.root_module.linkLibrary(lib);
b.installArtifact(exe);
const run_step = b.step("run", "Run the app");
const run_cmd = b.addRunArtifact(exe);
run_step.dependOn(&run_cmd.step);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
}
- src/glue.zig
const std = @import("std");
const Writer = std.Io.Writer;
comptime {
@export(&zig__Writer__write, .{ .name = "zig__Writer__write" });
@export(&zig__Writer__flush, .{ .name = "zig__Writer__flush" });
}
fn zig__Writer__write(w: *anyopaque, buffer: [*]const u8, size: usize) callconv(.c) void {
const writer: *Writer = @ptrCast(@alignCast(w));
writer.print("{s}", .{buffer[0..size]}) catch unreachable;
}
fn zig__Writer__flush(writer: *Writer) callconv(.c) void {
writer.flush() catch unreachable;
}
- src/glue.cpp
#include <cstddef>
extern "C" {
void zig__Writer__write(void* writer, const void* buffer, size_t size);
void zig__Writer__flush(void* writer);
void c__write(void* writer, const char *buffer, size_t size) {
zig__Writer__write(writer, buffer, size);
zig__Writer__flush(writer);
}
}
- src/main.zig
const std = @import("std");
const Io = std.Io;
pub fn main(init: std.process.Init) !void {
const c__write = @extern(*const fn (*anyopaque, [*]const u8, usize) callconv(.c) void, .{ .name = "c__write" });
const io = init.io;
var stdout_buffer: [1024]u8 = undefined;
var stdout_file_writer: Io.File.Writer = .init(.stdout(), io, &stdout_buffer);
const stdout_writer = &stdout_file_writer.interface;
const data_size = 1025;
const data: [data_size]u8 = @splat('#');
// Block 1: Failure
{
c__write(stdout_writer, &data, data_size);
}
// Block 2: Success
// {
// try stdout_writer.print("{s}", .{data});
// try stdout_writer.flush();
// }
}
The above code can be compiled and run normally in debug mode, but in ReleaseSafe/ReleaseFast/ReleaseSmall modes, when data_size >= buffer_size, it crashes with the following error info:
zzzzzz@fedora ~/D/d/exp-demo> zig build run --release=safe
Segmentation fault at address 0x2f
/home/zzzzzz/.config/Code/User/globalStorage/ziglang.vscode-zig/zig/x86_64-linux-0.16.0-dev.2682+02142a54d/lib/std/Io/File/Writer.zig:91:13: 0x10359f0 in drain (demo)
switch (w.mode) {
^
/home/zzzzzz/.config/Code/User/globalStorage/ziglang.vscode-zig/zig/x86_64-linux-0.16.0-dev.2682+02142a54d/lib/std/Io/Writer.zig:528:26: 0x10c6b63 in write (std.zig)
return w.vtable.drain(w, &.{bytes}, 1);
^
/home/zzzzzz/.config/Code/User/globalStorage/ziglang.vscode-zig/zig/x86_64-linux-0.16.0-dev.2682+02142a54d/lib/std/Io/Writer.zig:535:51: 0x10c38da in writeAll (std.zig)
while (index < bytes.len) index += try w.write(bytes[index..]);
^
/home/zzzzzz/.config/Code/User/globalStorage/ziglang.vscode-zig/zig/x86_64-linux-0.16.0-dev.2682+02142a54d/lib/std/Io/Writer.zig:1002:26: 0x10eb0ea in alignBuffer (std.zig)
return w.writeAll(buffer);
^
/home/zzzzzz/.config/Code/User/globalStorage/ziglang.vscode-zig/zig/x86_64-linux-0.16.0-dev.2682+02142a54d/lib/std/Io/Writer.zig:1024:25: 0x10c5a27 in alignBufferOptions (std.zig)
return w.alignBuffer(buffer, options.width orelse buffer.len, options.alignment, options.fill);
^
/home/zzzzzz/.config/Code/User/globalStorage/ziglang.vscode-zig/zig/x86_64-linux-0.16.0-dev.2682+02142a54d/lib/std/Io/Writer.zig:1140:52: 0x109a54f in printValue__anon_3725 (std.zig)
return w.alignBufferOptions(slice, options);
^
/home/zzzzzz/.config/Code/User/globalStorage/ziglang.vscode-zig/zig/x86_64-linux-0.16.0-dev.2682+02142a54d/lib/std/Io/Writer.zig:703:25: 0x109849c in print__anon_3302 (std.zig)
try w.printValue(
^
/home/zzzzzz/Documents/dev/exp-demo/src/glue.zig:11:17: 0x10981f1 in zig__Writer__write (glue.zig)
writer.print("{s}", .{buffer[0..size]}) catch unreachable;
^
src/glue.cpp:9:3: 0x1098104 in c__write (/home/zzzzzz/Documents/dev/exp-demo/src/glue.cpp)
zig__Writer__write(writer, buffer, size);
^
/home/zzzzzz/Documents/dev/exp-demo/src/main.zig:17:17: 0x1034b7f in main (demo)
c__write(stdout_writer, &data, data_size);
^
???:?:?: 0x7f87941835b4 in __libc_start_call_main (/lib64/libc.so.6)
???:?:?: 0x7f8794183667 in __libc_start_main_alias_2 (/lib64/libc.so.6)
???:?:?: 0x1033364 in ??? (???)
run
└─ run exe demo failure
error: process terminated with signal ABRT
failed command: /home/zzzzzz/Documents/dev/exp-demo/zig-out/bin/demo
Build Summary: 5/7 steps succeeded (1 failed)
run transitive failure
└─ run exe demo failure
error: the following build command failed with exit code 1:
.zig-cache/o/240121503831e5cb19f86f2bc801725a/build /home/zzzzzz/.config/Code/User/globalStorage/ziglang.vscode-zig/zig/x86_64-linux-0.16.0-dev.2682+02142a54d/zig /home/zzzzzz/.config/Code/User/globalStorage/ziglang.vscode-zig/zig/x86_64-linux-0.16.0-dev.2682+02142a54d/lib /home/zzzzzz/Documents/dev/exp-demo .zig-cache /home/zzzzzz/.cache/zig --seed 0x64a53a3a -Z04cde5472c702fe3 run --release=safe