A while ago, we looked at ArenaAllocators and why you should view their free as a noop. The short version is that, in order for a free or destroy to actually return memory to the arena, two conditions need to be met:

  1. The freed memory must have been the last allocated memory, and
  2. The freed memory must have been allocated on the Arena's current node (which is an internal detail of how the Arena grows)

Thus, given this code:

var a = try arena.alloc(u8, 100);
var b = try arena.alloc(u8, 100);
arena.free(b);
arena.free(a);

We can be certain that the memory for b will be returned to the arena, but can't say what will happen to a's memory. Why? b is freed because it was the last allocation and, by definition, had to have come from the arena's current node. After b is freed, a satisfies the first requirement: it becomes the last allocated memory. However, we don't know whether the allocation of b caused a new node to be created; the arena's current node may or may not be the one a came from.