2

In the below code, I have the function "get_specific_files". The objective of this function is to check if certain filenames contain some word, and then return all the files that contain that word in a list of strings (hopefully some kind of ArrayList of type []const u8, which will get converted to a slice).

However, if I stick anything whatsoever in that for loop other than just a simple function call, or a print("{s}\n", .{elems});, the data goes completely buggy.

For example, if I have the following code where the for loop is in the "get_specific_files" function, the data is printed out completely wrong:

var count: u8 = 0;

for (input) |elems| {
    print("{d}: {s}\n", .{count, elems});
    count += 1;
}

The result is something along the lines of:

1: file1.txt
2: file2.txt
3: weird unknown symbols
(repeat for however long the list is)

I am quite new to Zig, but I have been using C for a little while, so I am not new to pointers. I am confused about Zig pointers and allocation, so maybe that's the problem? But in the above code segment, if I just remove the count, everything prints correctly??

(The program thus far)

pub fn main() !void {
    var retval = try get_filenames();
    retval = try get_specific_files(retval);
}

fn get_specific_files(input: [][]const u8) ![][]const u8 {
    try out.print("Finding specific files . . .\n", .{});

    for (input) |elems| {

        if (std.mem.indexOf(u8, elems, "some_word") != null) {
            try foo(elems);
        }
    }
    return input;
}
 

fn get_filenames() ![][]const u8 {
    try out.print("Finding files . . .\n", .{});
    var dir = try std.fs.cwd().openDir("some/dir/foo/", .{.iterate = true});
    defer dir.close();

    var file_list = std.ArrayList([]const u8).init(allocator);

    var dir_iterator = dir.iterate();
    while (try dir_iterator.next()) |dir_content| {
        try file_list.append(dir_content.name);
    }

    const owned_slice = try file_list.toOwnedSlice();
    return owned_slice;
}

I was expecting the program to spit out the right files, but the unknown characters and everything is what actually happened.

1 Answer 1

2

try file_list.append(dir_content.name);

You do not own the memory that dir_content.name points to. You're saving a pointer to the iterator's internal memory. This pointer becomes invalid at the next step of the iteration. First, you need to save a copy in a memory that you control. This can be done via the allocator.dupe function.

The fixed code could look like this: try file_list.append(try allocator.dupe(u8, dir_content.name));

Sign up to request clarification or add additional context in comments.

2 Comments

Worked! Thank you! If you wouldn't mind, could you offer a little bit of an explanation on how editing the loop changed the data?
I've updated the answer to improve the explanation. I also recommend reading the Memory section in Zig's documentation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.