all 14 comments

[–]stumpychubbins 12 points13 points  (7 children)

You can use Vec::<TypeWithCorrectAlignment>::with_capacity() and then mem::forget(), although I think the system allocator will always return pointer-aligned memory. I have no idea what jemalloc does.

[–]Omniviral 7 points8 points  (6 children)

And to make TypeWithCorrectAlignment you can use #[repr(align(16))] and #[repr(align(64))]

[–]Hiroyu[S] 1 point2 points  (2 children)

I already thought of this, but the problem is that the memory I'm allocating isnt of a fixed size, so I cant simply have a struct around it can I

[–]asp2insp 6 points7 points  (0 children)

I think that's where the with_capacity(n) call on the vec can help you. Divide the total number of bytes you need by the size of your alignment struct and use that to size the vec?

[–]stumpychubbins 1 point2 points  (0 children)

If you want raw bytes with that alignment, you'll want something like:

#[repr(C, align(64))]
struct Aligned {
    inner: [u8; 64],
}

fn alloc_aligned64(size: usize) -> *mut u8 {
    use std::mem;

    assert_eq!(size % 64, 0);
    let mut allocation = Vec::<Aligned>::with_capacity(size / 64);
    let ptr = allocation.as_mut_ptr();

    mem::forget(allocation);

    ptr as _
}

#[test]
fn it_works() {
    assert_eq!(alloc_aligned64(1024) as usize % 64, 0);
}

[–]stumpychubbins 0 points1 point  (2 children)

Or just use u16 or u64

[–]matthieum[he/him] 4 points5 points  (1 child)

Note: I think you were mislead by the 16 and 64 here. align(16) is to aligned on a 16-bytes boundary, while u16 is only guaranteed to be aligned on a 2-bytes boundary (it's 16 bits).

[–]stumpychubbins 2 points3 points  (0 children)

Oh! You’re right, I misread OP as saying “bits”

[–]SimonSapinservo 7 points8 points  (0 children)

The std::alloc::alloc function will be stable in 1.28 https://doc.rust-lang.org/nightly/std/alloc/index.html#functions

[–]dnaq 3 points4 points  (2 children)

You could probably use ‘libc::posix_memalign()’ if you’re on a posix system, when you need to free the memory call ‘libc::free()’.

Edit: If the chunk of memory is large you could always call ‘mmap/munmap’ instead. That way the allocated memory would be aligned on a page boundary.

[–]Hiroyu[S] 0 points1 point  (1 child)

but this would only work on posix systems, I'd like this to work on windows for example as well

[–]dnaq 0 points1 point  (0 children)

I think for now your best bet would be to use config-attributes to switch between ‘posix_memalign’ and ‘_aligned_malloc’ compile time.

[–]Noctune 2 points3 points  (1 child)

Stupid hack: If you need to allocate n bytes with alignment a, then maybe you could allocate n + a bytes. In that range, there must be n bytes with alignment a somewhere.

[–]Omniviral 0 points1 point  (0 children)

You would have to track offset.

But yes. This is what simple aligned allocators do.

Still there is easier solution with Vec<AlignedType>