Hacker News new | ask | show | jobs
by deburo 43 days ago
Isn't using Arena just simplifying memory management, thereby reducing the amount of bugs as well?
1 comments

Use-after-free bugs are still possible, if an allocated memory chunk outlives the arena instance used for it. With C++-style owning containers such kind of errors is possible too, but it's not so frequent.

But arenas can't be used in any case. They are suitable only if large amounts of allocations take place once and need to be deallocated all at once. If reallocation of freeing of individual memory chunks is needed, arenas can't be used, so, it's needed to manage each allocation individually, for which containers is a better choice compared to manual memory management.

>But arenas can't be used in any case. They are suitable only if large amounts of allocations take place once and need to be deallocated all at once. If reallocation of freeing of individual memory chunks is needed, arenas can't be used

It's fairly straightforward to compose memory arenas with a pool allocator in these circumstances.

All of this is false.

1) An allocated memory chunk cannot outlive its arena (leaks are impossible). You probably mean a stale reference? The arena is put at such a level in the memory hierarchy that this bug becomes impossible. The bug here would be that the allocation was done in the wrong arena. In C this would be avoided by putting temporary arenas in a local function scope by passing them as parameters. Fool proof references require C++ smart pointers. This is one example of you mixing concepts. Smart pointers/containers can still be used with arenas.

2) You mix up arenas and bump allocators. An arena can also use a pool allocator for example. Arena refers to the concept of scoping blocks of allocations.

3) Individual deallocations and arenas are not exclusive, for example using pools. But even with bump allocators free lists are a thing (and linked lists are more attractive in bump allocators because of locality).

1) In practice, this is not true, especially if you implement unwinding in your arena.

You probably don't want to have an Arena in main, and you do all of your allocations from there, for example. That "just" leaks everything.

Here's a classic Arena-with-rewind bug:

  {
    Arena a;
    avec<int> v(a);
    {
      RewindMark rm(a);
      v.push(1); v.push(1); // Trigger resize
    }
    v[2] // Oh no! The underlying data array has been deallocated
  }
Thanks. This is a good illustration of how data structures aren't cleanly separable from memory management strategies.
I’m sorry, but I look at this code and I can immediately see the bug? Instead of a rewind mark I personally create a local arena from the outer arena. If any allocations leak to the parent scope I put the code in a local function that takes the parent arena as a parameter. Again, if you’re so inclined you can use Rust or C++ to create smart pointers that catch this at runtime or even compile time, it’s just not a real issue for me at this point, reducing the value of complicated compiler machinery leading to bad build times.
That's right! I made the example in such a way that it is obvious what the bug is, for pedagogical reasons :-). This particular bug is a bit trickier to spot when you have more complex programs, and is something that I have seen in real (large) codebases. Your inner/outer arena sounds exactly like the same thing, though?

Generally, it's best to avoid the rewind trick, IMO, it makes it difficult to create composable programs.