Hello there, I’m new to Zig, have a lot of questions. Here is one of them:
I’ve written a simple program to download files and it works. But then I started experimenting. According to the Zig docs I replaced GeneralPurposeAllocator with ArenaAllocator, which means there is no more need to free manually, so I omitted deinit of objects. After that I even disabled file.close, argsFree and arena.deinit, but the code still compiles and works. I wonder why - shouldn’t this have led to memory leaks?
Here is the program (fetch.zig):
const std = @import("std");
const fs = std.fs;
const print = std.debug.print;
const State = struct {
allocator: std.mem.Allocator,
fn fetch(self: State, url: []const u8) !void {
const uri = std.Uri.parse(url) catch unreachable;
const name = fs.path.basename(url);
var client = std.http.Client{ .allocator = self.allocator };
// defer client.deinit();
var server_header_buffer: [1024]u8 = undefined;
var req = try client.open(
.GET,
uri,
.{ .server_header_buffer = &server_header_buffer }
);
// defer req.deinit();
try req.send();
try req.finish();
try req.wait();
if (req.response.status != .ok) {
return error.HttpFailed;
}
const cwd = fs.cwd();
const file = try cwd.createFile(name, .{});
// defer file.close();
var buffer: [1 << 14]u8 = undefined;
var i: u64 = undefined;
print("Fetching data\n", .{});
while (true) {
i = try req.read(&buffer);
if (i == 0) break;
_ = try file.write(buffer[0..i]);
}
print("Successful download\n", .{});
}
fn parseArgs(self: State) !void {
const args = try std.process.argsAlloc(self.allocator);
if (args.len == 2) {
try self.fetch(args[1]);
} else
print("Usage: fetch [URI]\n", .{});
}
};
pub fn main() !void {
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
// defer arena.deinit();
const state = State {
.allocator = arena.allocator()
};
try state.parseArgs();
}