| ▲ | Panzerschrek 5 hours ago |
| I think it's a reasonable price to have your own containers (vector/unique_ptr replacements), if you wish to use a non-standard approach for memory allocation. Many people do this, like Qt with QVector. But do you really need arenas? Does doing allocations in a traditional way creates a bottleneck in your specific use-case? Or you just want to justify broad manual memory management (with its bugs and secure vulnerabilities) in hope to gain (or not) a tiny amount of extra performance? |
|
| ▲ | eska 5 hours ago | parent | next [-] |
| Respectfully, you do not seem to understand this topic well. If the C++ standard library design abstracted memory allocation correctly, you’d still be able to use containers and algorithms and not even notice that their allocation strategy uses the heap, stack, a bump allocator, a pool, etc |
| |
| ▲ | tardedmeme 3 hours ago | parent | next [-] | | Would that even work? If you use std::vector within an arena, you allocate twice as much memory as you need to, since the old arrays can't be deallocated. You might want to use std::deque instead. Memory management is not independent from data structures - std allocators smell to me like another failed experiment, like auto_ptr mentioned in another comment. Also, with allocators you can replace new and delete, but you can't implement anything that doesn't fit into the new/delete paradigm, like any allocation strategy that requires moving objects. | |
| ▲ | Panzerschrek 5 hours ago | parent | prev | next [-] | | I understand how C++ standard containers are designed. They are designed in such a way, so that they don't store a pointer to an allocator instance inside. This allows to save memory in the most cases (where the standard allocator is used). Overriding an allocator is possible, but only with some another global allocator (via a template argument), with no possibility to specify a per-object allocator. As I know in newer C++ standards there is something which allows to workaround this issue. Or at least there are proposals for this. | | |
| ▲ | tardedmeme 3 hours ago | parent [-] | | Each container stores an allocator instance inside, not a pointer to one. If you need shared state, it's up to you to make each allocator instance contain a pointer to the shared state. |
| |
| ▲ | Maxatar 4 hours ago | parent | prev [-] | | Respectfully, your way out of date with your understanding of this topic. C++ added polymorphic memory allocators in C++17 along with polymorphic versions of all standard library containers under the std::pmr namespace, so that you have std::pmr::vector, std::pmr::map, etc... all of which fully abstract out the details of memory allocation. |
|
|
| ▲ | deburo 5 hours ago | parent | prev [-] |
| Isn't using Arena just simplifying memory management, thereby reducing the amount of bugs as well? |
| |
| ▲ | Panzerschrek 5 hours ago | parent [-] | | 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. | | |
| ▲ | eska 5 hours ago | parent | next [-] | | 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). | | |
| ▲ | my-next-account 4 hours ago | parent [-] | | 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
}
| | |
| ▲ | eska 14 minutes ago | parent | next [-] | | 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. | |
| ▲ | tardedmeme 3 hours ago | parent | prev [-] | | Thanks. This is a good illustration of how data structures aren't cleanly separable from memory management strategies. |
|
| |
| ▲ | Jtarii 5 hours ago | parent | prev [-] | | >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. |
|
|