Search code examples
memory-managementmemory-leakszig

Am I supposed to free unused slice spaces in Zig?


Suppose I allocate a slice and fill it only partially, like

fn allocSlice(allocator: std.mem.Allocator, n_items: u8) ![]u8 {
  var my_slice = try allocator.alloc(u8, 256);
  for (0..n_items) |i| {
    my_slice[i] = @truncate(i);
  }
  return my_slice[0..n_items];
}

Since I didn't use the allocated space between n_items and 256, will that leak? Will it remain allocated to that same slice (that was returned from the allocSlice function) and be freed when that partial slice is freed?

Or should I free the unused space before returning?, like

  allocator.free(my_slice[n_items..256]);

Update with new findings

Turns out the approach above causes the program to crash with the following message:

panic: Invalid free

But also if I return the (partial) slice from the function and later try to free it I get a different error:

error(gpa): Allocation size 256 bytes does not match free size 12.

So it turns out neither of these approaches is correct. What is, then?


Solution

  • There's no such thing as "partially" freeing a slice. You either keep or free the whole thing.

    You can try allocator.resize, which depending on the implementation might be able to shrink the buffer in-place (implementations are allowed to refuse to do this however), or allocator.realloc which will return a new slice with only the contents up to what you requested in it (or a larger slice with uninitialised memory at the end if you request a larger size), while invalidating the old slice.

    Generally, if you know in advance how much memory you're going to need you should only request that much memory in the first place. resize/realloc are more useful for cases where how much memory you need can't be determined in advance (and there are already types in the standard library like ArrayList which take care of the common cases of this occurring, so you usually don't have to write that kind of code from scratch unless you're writing low level IO or data structure code).