Struct instance is empty

I’m stuck on this problem, I’m not sure how to proceed. I’ve tried debugging using print and gdb, but I’m unable to figure out my mistake. Any help is appreciated.

In my main.zig, res is empty and in gdb when I try to print res it says there is no reference to res.

There are two files main.zig and browser.zig.

// zig: 0.13.0
// main.zig
// allocator: generalPurposeAllocator

    var t = browser.Tab.init(buffer[0..bufferReadLen], allocator) catch |err| {
        print("There was a problem with the URL: {}\n", .{err});
        return;
    };
    defer t.deinit();

    const rawRes = t.request("/index.html") catch |err| {
        print("There was an error making that request: {}\n", .{err});
        return;
    };

    const res = browser.Response.parseResponse(rawRes, allocator) catch |err| {
        print("There was an error parsing that response: {}\n", .{err});
        return;
    };
    defer res.free(allocator);
    print("Body: {s}\n", .{res.body}); // prints the []const u8 as expected

    const html = browser.renderHTML(res.body); // res.body is empty here
    print("Parsed Body: {s}\n", .{html});
    print("Body: {s}\n", .{res.body}); // is empty
// browser.zig
const struct = Response {
  body: []const u8,

  pub fn parseResponse(...) {
    ...
    const res = try allocator.create(Response);
    res.* = Response{ ..., .body = iter.rest() };
    return res;
  }
}

From what you have shown I think it is most likely that

iter.rest() returns a slice that involves or points to temporary memory (memory that is allocated on the stack in some kind of buffer) so once there is sufficient shuffling around with the stack, the data points to something else, but because you say that the body is empty, it seems as if the pointer/length of the slice itself changes. So you could try to print the res.body.ptr with format {*} and res.body.len with {}, where it worked and was empty and then compare the addresses and length.

You also could try to use the allocator to dupe the body and see if that fixes it, if it does it is pretty sure that that is the problem.
So try if something like this fixes it:

res.* = Response{ ..., .body = try allocator.dupe(u8, iter.rest()) };

If it does, you have to investigate why iter.rest() gives you memory that has a lifetime that is too short.

If my guess isn’t right, it would be helpful to have more info.

And welcome to the forum!

5 Likes

Thank you for the response Sze :slight_smile:

That worked. I’ll read into lifetimes and the doc you provided. That was very helpful. Thanks again.

That does make sense. Initially I was not doing the allocation and returning a copy of the instance. It was empty too. I’ll try out a few iterations based on your suggestion.

I’m glad I asked here, as it would have been a while before I realized that iter.rest() points to a temporary memory.

1 Like