4 ms·
> In other words, you may treat the operating system as “the ultimate garbage collector”—freeing memory when it is unnecessary will simply waste both your and t
by gjulianm 4y ago
> In other words, you may treat the operating system as “the ultimate garbage collector”—freeing memory when it is unnecessary will simply waste both your and the user’s time, and lead to code complexity and bugs that would otherwise not exist. Unfortunately, many popular programming education resources teach that cleanup code is always necessary. This is false.
I disagree. One, I think the set of C code where both "allocates enough pointers that calling 'free' is too complicated" and "memory leaks are not a problem due to short runtime/low memory usage" is very small. Two, having a pattern where calling free is too complicated might indicate problems with the code: if your code makes it hard to manage lifecycles, I bet it makes several other things harder than they should be. Three, one should think what happens when that code is used in other places: writing proper lifecycle management at the beginning is easier than doing it when it's used as a library.
> This simplifies all codepaths in this system. The parsing code becomes simpler, because it does not have to have any cleanup code whatsoever. The calling code becomes simpler, because it does not have to manage the lifetime of the parsed tree independently. And finally, the allocator code itself remains nearly trivial, and lightning fast.
Again, disagree. The calling code becomes more complex because now you have to link the arena to the object it creates. It's very easy to make the mistake of passing the object without the associated arena, then releasing the arena, and boom the object is now garbage. And, as I saw in another comment, cleanup might involve more things than just "freeing memory", so you might end up iterating all the structures nevertheless. On the other hand, with RAII and smart pointers (or GC, or refcounting), you don't have to manually iterate through the structure and free and do cleanup. When things go out of scope, they get cleaned up and deallocated, and that's it.
But the main issue is memory fragmentation and overallocation. Precisely the example of a JSON tree, where possibly multiple conversions are done and auxiliary structures are allocated, is where I think not all things will be allocated in a perfectly linear fashion, and therefore freeing in a stack allocator will lead to a lot of unreachable memory inside of the stack. I find it surprising that a post that talks about arena allocators doesn't even mention "fragmentation".
Are arenas a good tool? Yes, and like every good tool, they have advantages and pitfalls. This post makes it look like they're better than RAII and garbage collectors, and that's false. And the main problem isn't that it does so by virtue of having different opinions, but by hiding the pitfalls of arena allocators.
- williamcotton 4y agoI use arenas for HTTP request handlers. The JSON built or parsed is only going to be around for the lifetime of the request. It's much simpler and faster to use an arena than to do reference counting wrapped around malloc/free. Here's an example where in a commit I swapped in an arena: https://github.com/williamcotton/express-c/commit/4ae53f38e3a85ed6109e5f6523cbb98aa15b20b9 https://github.com/williamcotton/express-c/commit/4ae53f38e3...
- gjulianm 4y agoI'm not saying that arena allocators are a bad tool. It seems like a very good fit for your case, where the lifetime of a request is pretty well constrained, and issues like fragmentation and overallocation won't matter too much. But still I think the OP completely misses the discussions of these aspects.