Laney
Laney

Reputation: 1649

std.json.parse and memory management

I have the following zig code (simplified):

const allocator = ...;

const Entry = struct {
    name: []u8,
};

fn list() ![]u8 {
    var entries = try std.json.parse([]Entry, ...);
    defer std.json.parseFree([]Entry, entries, ...);
    return entries[0];
}

fn main() !void {
    const e = try list();
    ...
}

Everything is (de)allocated with allocator.

I'd like to return entries[0] and recycle everything else. The problem is that parseFree here recycles everything including entries[0] so I can't seemingly use this function.

So what's the most effective way to do that without copying? What if Entry is a big structure and I want to return just one its field, say Entry.name (and, again, recycle everything else)?

Upvotes: 1

Views: 911

Answers (1)

kristoff
kristoff

Reputation: 642

The quickest way of achieving what you want is to not use parseFree but instead:

const first = entries[0].name;
for (entries[1..entries.len]) |e| alloc.free(e.name); // frees individual strings
alloc.free(entries); // frees the array of structs

return Entry { .name = first };

This is fairly straightforward but relies on understanding how memory is allocated by std.json and the implementation might one day want to allocate things differently, causing the code above to break.

Because of that, my recommendation would be to just copy the string and only resort to this type of extra complexity once you have demonstrated that avoiding that copy brings perceivable benefits.

Upvotes: 1

Related Questions