I am building a library to link with two types of program.
- a zig wrapper executable linked with this library dynamically, to work as a CLI application.
- a shared library produced by statically linking this library with C(.c/.h) wrapper. This then will be used on a java application through Java Native Interface.
I just said two types but this issue is focused on program type 1
.
The latter is there to reason why things are exported as such / allocator is declared there, in my code below.
So while testing out a file-read on this library, I faced a segfault
, and am having a hard time debugging it.
I am currently on WSL2 Ubuntu with zig 0.13.0 compiling natively(x86_64-linux-gnu), and these are the 4 files of code I am currently testing on.
src/lib.zig
const std = @import("std");
export fn read(s: [*:0]const u8) callconv(.C) [*:0]const u8 {
// GPA
var gpa = std.heap.GeneralPurposeAllocator(.{ .never_unmap = true, .retain_metadata = true, .verbose_log = true }){};
const allocator = gpa.allocator();
// FILE
const path: []const u8 = std.mem.span(s);
const file = std.fs.cwd().openFile(path, .{}) catch @panic("oh nyo");
std.log.info("opening file: {s}", .{path});
defer file.close();
// READ
const reader = file.reader();
// will expose a release to caller later
const buff: []u8 = allocator.alloc(u8, 256) catch @panic("oh nyoo");
// ERR: readAll fails with "Segmentation fault at address 0x3"
std.log.info("the line under throws segfault @ 0x3 in x86_64-linux-gnu built library", .{});
// tried readUntilDelimiterOrEofAlloc first, pulled allocator away for clearance
const read_len = reader.readAll(buff) catch @panic("oh nyooo");
std.log.info("unreachable by segfault", .{});
buff[read_len] = 0;
// content
const result: [*:0]u8 = @ptrCast(buff);
return result;
}
test {
const string = @as([:0]const u8, "file.txt").ptr;
const result = read(string);
const span: []const u8 = std.mem.span(result);
try std.testing.expect(std.mem.eql(u8, span, "wow hello text"));
}
src/main.zig
const std = @import("std");
extern fn read(_s: [*:0]const u8) [*:0]const u8;
pub fn main() !void {
const filename_c = @as([:0]const u8, "file.txt").ptr;
const content_c = read(filename_c);
const content = std.mem.span(content_c);
std.log.info("file contains: {s}\n", .{content});
}
file.txt
wow hello text
build.zig
const std = @import("std");
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const lib_core = b.addSharedLibrary(.{
.name = "core_zzg",
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
.link_libc = true
});
const exe = b.addExecutable(.{
.name = "zzg",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.link_libc = true
});
exe.linkLibrary(lib_core);
b.installArtifact(lib_core);
b.installArtifact(exe);
}
build.zig.zon
is completely same as the one produced by zig init
.
and… that’s it. If I run zig test src/lib.zig
, it works without any problem.
But if I execute the output of zig build
, the segfault is thrown with a complete output below.
info: opening file: file.txt
info(gpa): small alloc 1024 bytes at u8@7f07124c1000
info: the line under throws segfault @ 0x3 in x86_64-linux-gnu built library
Segmentation fault at address 0x3
/snap/zig/11625/lib/std/mem.zig:1062:48: 0x7f0712504138 in indexOfSentinel__anon_3949 (core_zigzag)
Segmentation fault (core dumped)
I would like to know what’s the reason behind this behavior and grasp any possible resolution.
Other tips regarding how I should have done something in some other way considering c-zig linking is also very welcome.
I am greeting awkwardly with this language since just a week ago, and would much appreciate if anyone could lead me to a better understanding