I’m learning zig (using 0.16 nightly) and I’m trying to read a file and print out each byte. The code does indeed print out each byte as expected but at the end throws an error saying there was a memory leak. What am I doing wrong here and is there a better way to do this?
You are calling a function which allocates the required buffer for you, puts the file contents in it and returns it to you. Then you return that buffer.
This buffer ends up here in file_contents.
You can go and print it, but never deallocate said buffer, but at the beginning of your main function
you created an assert that no leaks happen when the function finishes.
This assert fails since you didn’t deallocate the buffer, that’s your memory leaks.
One way, you can fix that, is by inserting
defer allocator.free(file_contents);
between the initialisation of file_contents/the call to get_file_contents and your loop for printing the contents.
The DebugAllocator can help you find where memory was allocated since it dumps a stack trace for every allocation that leaked (that were not freed) when you .deinit() it. For example, your program should print something like
/home/user/.cache/zig/lib/std/Io/Reader.zig:721:37: 0x11796df in readAlloc (std.zig)
const dest = try allocator.alloc(u8, len);
^
/tmp/tmp.zig:28:38: 0x11778e9 in get_file_contents (tmp.zig)
const data = try reader.readAlloc(allocator, file_size);
^
/tmp/tmp.zig:12:48: 0x1177d39 in main (tmp.zig)
const file_contents = try get_file_contents(io, allocator, "/path/to/file.txt");
^
/home/user/.cache/zig/lib/std/start.zig:714:37: 0x11784f3 in callMain (std.zig)
const result = root.main() catch |err| {
^
/home/user/.cache/zig/lib/std/start.zig:242:5: 0x1177581 in _start (std.zig)
asm volatile (switch (native_arch) {
You can see that the allocation caused inside readAllocwas never freed.
Also, as a convention, functions that need to allocate memory will have an Allocator argument. You can then easily spot what functions might be causing an allocation. Notice that you provided an allocator to the readAlloc function, but also to your get_file_contents function and std.Io.Threaded.init.