How to implement pointer assignment to a pointer in rust

c code

unsigned char** adata = ptr;
adata[-1] = another_ptr;

Could you describe the high-level behavior you're trying to implement? Idioms from C usually don't translate one-to-one into Rust.

1 Like

Rust’s memory rules are more complicated than C’s, so it’s best to avoid raw pointers when you can: The safe APIs will enforce the rules for you, but it’s your responsibility when working with unsafe.

To answer your actual question, though, you’ll want ptr::offset and ptr::write:

unsafe fn f(adata: *mut *const u8, another_ptr: *const u8) {
    adata.offset(-1).write(another_ptr);
}

I want to implement this

static inline void **alignPointer(void **ptr, size_t alignment) {
    return (void **)((intptr_t)((unsigned char *)ptr + alignment - 1) & -alignment);
}

extern "C" void *MemoryAllocAlign(size_t size, size_t alignment) {
    ASSERT(size > 0);

    void **origin = (void **)malloc(size + sizeof(void *) + alignment);
    ASSERT(origin != NULL);
    if (!origin) {
        return NULL;
    }
    void **aligned = alignPointer(origin + 1, alignment);
    aligned[-1]    = origin;
    return aligned;

}

extern "C" void MemoryFreeAlign(void *aligned) {
    if (aligned) {
        void *origin = ((void **)aligned)[-1];
        free(origin);
    }
}

This is my implementation

fn align_size(v: size_t, n: size_t) -> size_t {
    v.wrapping_add(n).wrapping_sub(1) & !n.wrapping_sub(1)
}

unsafe fn align_ptr(ptr: *mut u8, n: sizt_t) -> *mut u8 {
    ptr.add(ptr.align_offset(n)).cast()
}

unsafe fn fast_malloc(&self, size: size_t, alignment: size_t) -> *mut c_void {
        if cfg!(target_os = "linux") && unlikely(size == 0) {
            return ptr::null_mut();
        }
        
        let udata = libc::malloc(size + mem::size_of::<*mut  c_void>() + alignment) as *mut c_uchar;
        if  udata.is_null(){
            return ptr::null_mut();
        }
        let adata = align_ptr(udata.offset(1), alignment );
        //adata[-1] = udata;//I don’t know how to impl this 
        //return adata;
    }
    

I’m beginner, so translate one-to-one into Rust. :sweat_smile:

The low-level way to allocate/free memory with a specific size and alignment in Rust is this:

let layout = std::alloc::Layout::from_size_align(size, alignment).unwrap();
assert!(layout.size() > 0);
// will be null if allocation failed, just like in C
// SAFETY we've asserted that the layout has size > 0
let ptr: *mut u8 = unsafe { std::alloc::alloc(layout) };
// later...
// SAFETY ptr was allocated with this layout
unsafe { std::alloc::dealloc(ptr, layout); }

But it's very likely that there's a high-level container in std or another library that will handle allocation and deallocation for you automatically, preventing bugs from use-after-free/double free/uninitialized access/etc. How is MemoryAllocAlign used in the C code you're porting?

1 Like

Yeah , It is the memory allocation function of the Mat class in OpenCV, which can make data alignment, data pointer alignment, and improve data access performance

I'd suggest you first figure out what kind of data structure the Mat class implements, and then look into how to represent that data structure in Rust. For example, if the underlying storage for the class turns out to be a heap-allocated contiguous block of float values, you could use a Vec<f32> in Rust. Porting function-by-function from C/C++ is going to be tedious, and you won't be able to take advantage of the extra safety/expressiveness features that Rust offers (because you'll be working with raw pointers the whole time).

1 Like

What about using the align_to() method on a &[u8]?

Although to X-Y the question, there are probably better ways to achieve your end goal by skipping pointer manipulations altogether.

Thanks, I’ll try.

thanks

thank u for ur reply.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.