Hi rustaceans!
I wanted to build an arena allocator as a little exercise for myself and I came up with this:
use std::{alloc::{Layout, alloc, dealloc, handle_alloc_error}, ptr::NonNull};
use std::cell::Cell;
pub struct Arena {
ptr: Cell<NonNull<u8>>,
ptr_pos: Cell<usize>,
capacity: usize,
}
impl Arena {
pub fn new(capacity: usize) -> Self {
if capacity > isize::MAX as usize {
panic!("cannot alloc more than isize::MAX bytes");
}
if capacity == 0 {
panic!("capacity cannot be 0");
}
let layout = Layout::array::<u8>(capacity).expect("we checked if the capacity was less than isize::MAX byes");
// SAFETY: we checked if the capacity was 0
let ptr = unsafe {
alloc(layout)
};
if ptr.is_null() {
handle_alloc_error(layout);
}
let ptr = Cell::new(NonNull::new(ptr).expect("we checked if ptr was null"));
Self {
ptr,
ptr_pos: Cell::new(0),
capacity,
}
}
pub fn alloc<T>(&self, data: T) -> Option<&mut T> {
self.ptr_pos.update(|pos| pos + size_of::<T>());
if self.ptr_pos.get() > self.capacity - 1 {
return None;
}
let ptr = self.ptr.get().as_ptr() as *mut T;
unsafe {
ptr.write(data);
}
self.ptr.update(|ptr| unsafe { ptr.add(size_of::<T>()) });
// SAFETY: the pointer is valid non-null
unsafe {
Some(ptr.as_mut().expect("the pointer isn't null"))
}
}
}
impl Drop for Arena {
fn drop(&mut self) {
self.ptr.update(|ptr| unsafe {ptr.sub(self.ptr_pos.get())});
let layout = Layout::array::<u8>(self.capacity).expect("capacity isn't 0");
unsafe {
dealloc(self.ptr.get().as_ptr(), layout);
}
}
}
but the problem with this Arena is that it doesn't align items properly and reading/writing from unaligned pointers is UB, so my question is: how can I make sure that my pointer is properly aligned for a type while still allowing many different types within one Arena.
5 posts - 2 participants
Read full topic
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | Type erasure and dyn lifetime in a NonNull/Box struct field | 0 | 8.55 | 04-10-2026 |
| 2 | Array initialization post declaration | 0 | 16.79 | 06-10-2026 |
| 3 | Does my lockfree stack impl look correct? | 0 | 6.06 | 05-10-2026 |
| 4 | Why no Dependent Matrix Type? | 0 | 5.16 | 08-10-2026 |
| 5 | Trait object with associated types in field - requires generic param? | 0 | 11.08 | 07-10-2026 |
| 6 | Are there wait-free priority queue crates? | 0 | 16.09 | 05-10-2026 |
| 7 | Calling static C++ method from Rust | 0 | 9.94 | 04-10-2026 |
| 8 | What's everyone working on this week (41/2026)? | 0 | 20.34 | 06-10-2026 |
| 9 | Strategies for dyn trait objects with optional behavior? | 0 | 7.12 | 06-10-2026 |
| 10 | Why is f32/f64::sqrt not const? | 0 | 22.72 | 06-10-2026 |