#I want to use a structure to handle `argv` and `env`, but I don't know how to do it

1 messages · Page 1 of 1 (latest)

silver ibex
#

As the title suggests, I want to separate argv and env from the main() function and handle them separately, but I am inexperienced and do not know how to operate them

const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();
    defer {
        const deinit_status = gpa.deinit();
        if (deinit_status == .leak) @panic("TEST FAIL");
    }

    const argv = try std.process.argsAlloc(allocator);
    defer std.process.argsFree(allocator, argv);

    const env = std.os.environ;

    for (argv) |value| {
        std.debug.print("{s}", .{value});
    }

    for (env) |value| {
        std.debug.print("{s}", .{value});
    }
}

tropic flint
#

std.os.environ and std.process.argsAlloc are not tied to the main function, you can access them wherever you want

weary marten
#

well to be clear, std.os.environ is tied to the startup code, it will be undefined if you create your own startup code

#

same with std.process.argsAlloc

#

but yeah, you can use them anywhere of course (assuming you're using the main function)

silver ibex
#

I estimate that I only need an example of creating and destroying, and I may understand how to do it

weary marten
#

what errors are you getting?

silver ibex
# weary marten what errors are you getting?

Such as type errors, incorrect memory releases, etc. There was indeed a version before that could not run normally during compilation, but it made me feel too frustrated. I have already deleted it

weary marten
tropic flint
silver ibex
#

envParameter.zig

const std = @import("std");

pub const envParameter = struct {
    arg: []const [:0]u8,
    env: [][*]u8,

    pub fn get(allocator: std.mem.Allocator) !envParameter {
        const arg = try std.process.argsAlloc(allocator);
        const env = std.os.environ;
        return envParameter{ .arg = arg, .env = env };
    }

    pub fn del(self: envParameter, allocator: std.mem.Allocator) void {
        std.process.argsFree(allocator, self.arg);
    }
};

main.zig

const std = @import("std");
const envParameter = @import("envParameter.zig");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();
    defer {
        const deinit_status = gpa.deinit();
        if (deinit_status == .leak) @panic("TEST FAIL");
    }

    const p = try envParameter.envParameter.get(allocator);

    for (p.arg) |value| {
        std.debug.print("{s}", .{value});
    }

    for (p.env) |value| {
        std.debug.print("{s}", .{value});
    }
    p.del(allocator);
}

#
install
└─ install RAZOR
   └─ zig build-exe RAZOR Debug native 1 errors
C:\Users\Raum\AppData\Local\Microsoft\WinGet\Packages\zig.zig_Microsoft.Winget.Source_8wekyb3d8bbwe\zig-windows-x86_64-0.13.0\lib\std\mem.zig:756:57: error: invalid type given to std.mem.span: [*]u8       
                .Many => if (ptr_info.sentinel == null) @compileError("invalid type given to std.mem.span: " ++ @typeName(T)),
                                                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Users\Raum\AppData\Local\Microsoft\WinGet\Packages\zig.zig_Microsoft.Winget.Source_8wekyb3d8bbwe\zig-windows-x86_64-0.13.0\lib\std\mem.zig:782:31: note: called from here
pub fn span(ptr: anytype) Span(@TypeOf(ptr)) {
                          ~~~~^~~~~~~~~~~~~~
referenced by:
    format__anon_7274: C:\Users\Raum\AppData\Local\Microsoft\WinGet\Packages\zig.zig_Microsoft.Winget.Source_8wekyb3d8bbwe\zig-windows-x86_64-0.13.0\lib\std\fmt.zig:185:23
    print__anon_4520: C:\Users\Raum\AppData\Local\Microsoft\WinGet\Packages\zig.zig_Microsoft.Winget.Source_8wekyb3d8bbwe\zig-windows-x86_64-0.13.0\lib\std\io\Writer.zig:24:26
    remaining reference traces hidden; use '-freference-trace' to see all reference traces
error: the following command failed with 1 compilation errors:
C:\Users\Raum\AppData\Local\Microsoft\WinGet\Packages\zig.zig_Microsoft.Winget.Source_8wekyb3d8bbwe\zig-windows-x86_64-0.13.0\zig.exe build-exe -ODebug -Mroot=C:\Users\Raum\Documents\rz\RAZOR\src\main.zig --cache-dir C:\Users\Raum\Documents\rz\RAZOR\.zig-cache --global-cache-dir C:\Users\Raum\AppData\Local\zig --name RAZOR --listen=-
Build Summary: 2/5 steps succeeded; 1 failed (disable with --summary none)
install transitive failure
└─ install RAZOR transitive failure
   └─ zig build-exe RAZOR Debug native 1 errors
#

error: the following build command failed with exit code 1:
C:\Users\Raum\Documents\rz\RAZOR\.zig-cache\o\83d4a787f2972ef8aa51f89f0140834d\build.exe C:\Users\Raum\AppData\Local\Microsoft\WinGet\Packages\zig.zig_Microsoft.Winget.Source_8wekyb3d8bbwe\zig-windows-x86_64-0.13.0\zig.exe C:\Users\Raum\Documents\rz\RAZOR C:\Users\Raum\Documents\rz\RAZOR\.zig-cache C:\Users\Raum\AppData\Local\zig --seed 0xf923367f -Z1b8a870c5a6a3dcb
weary marten
#

yeah you can't print a [][*]u8 with the stdlib formatter

#

so the p.env printing stuff

tropic flint
#

the env field in envParameter should probably have type [][*:0]u8 - that is, sentinel terminated

weary marten
#

yes

tropic flint
# silver ibex How can I fix this error

change the type of the env field.
the error is due to std.debug.print not knowing how to print a [*]u8 as a string - very reasonable, since the type has no indication for the number of characters in the string.
by changing the type to [][*:0]u8 (that is, a slice of pointers to sequences of u8s, terminated with 0s), the printing function will know how to obtain the length of the strings (by searching for the 0 sentinel)

silver ibex
tropic flint
#

you're welcome ^-^

#

also I think you've found a bug...

#

this is covariance over mutable references

#

a classic type system unsoundness

#

well, I'll call this an oversight, not bug

#

still, I'll look into that - it might be worth opening an issue about

#

and here's the issue:

test {
    var x: [*:0]const u8 = "abc";
    const good_ref: *[*:0]const u8 = &x;
    const evil_ref: *[*]const u8 = good_ref; // this coercion is bad!

    evil_ref.* = @as([*]const u8, &.{ 'a', 'b', 'c' });
    // oops! `x` is now storing a
    // non-sentinel-terminated pointer!
}

gonna file a bug report about it

silver ibex
weary marten
#

library for what?

silver ibex
weary marten
silver ibex
# weary marten what’s your problem exactly?

You said before,
well to be clear, std.os.environ is tied to the startup code, it will be undefined if you create your own startup code
That is to say, it is unusable, so I need to find an alternative solution in std, but I don't know which one to use