Preventing Rust from deallocating the memory

I have used Rust for some part of my project and created cdylib , but the problem is Rust memory management system deallocates the memory which must not be . so how do i prevent Rust from doing that?

i get the data as *mut u8 from C side and create Vec from that memory without allocating new memory , so now i have to prevent Vec to deallocate the memory

tested :
box::leak not working
std::mem::manuallydrop not working too

Vec deallocates its buffer when it goes out of scope. If you don't want it deallocated, don't create a Vec. Instead, use (for instance) std::slice::from_raw_parts to make a slice reference, which does not own its memory and won't try to deallocate it.

(Worth pointing out - calling Vec::from_raw_parts on a pointer that wasn't created from a Vec in the first place is already UB.)

11 Likes

but the problem is the prev code which is written before uses Vec , so i have only two options here looking in all of the code base and change all of it from Vec to slice which will break entire project !

other choice is to allocate memory for vec , copy everything from that slice to vec and then after processing copy back everything to that slice . i dont want to allocate too much mem so i went for straight creating a vec so im seeking for a way to prevent a vec from doing that

by the whats meaning of UB?xD

It may break less than you think. Vec can auto-deref to […], and so most call sites that pass a vector will still work unchanged if the argument type is changed to a slice.

2 Likes

im not sure really but its time consuming , isnt there any way really?

If the existing code uses Vec, and does stuff that needs to use a Vec and not a slice (to grow/shrink/otherwise touch the allocation) then that is exactly why you cannot pass your unsized char * from C.

Your options are indeed either to make a copy or to change the code so that it does not use Vec.

3 Likes

no the code base does not use shrink and etc like that so using vec instead of slice could be valid choice , if i could prevent vec from deallocating the memory

Then it should be trivial (and more accurate) to change it to use &[T].

8 Likes

If we forget for a moment than calling Vec::from_raw_parts on a C pointer is UB, isn't std::mem::forget enough to avoid the drop on the Vec and prevent the memory to be deallocated?

@SkillfulElectro Btw, UB means Undefined Behavior: to put it simple from that point on your program can do completely random things, even in places unrelated from where you constructed the vector. Using a slice is the better choice here.

1 Like

well sadly std::mem::forget did not do it too

How are you using it?

1 Like
let mut information = info{
        row : data.row , 
        column : data.column ,
        data :  unsafe {data.data_as_vec().expect("NULL DATA")} ,
    };

   

    smth!(&mut information);



    std::mem::forget(information.data);

this is ending of my function so information.data must remain valid but in C side i get double free error when my function returns

From the small piece of code you showed us I guess you can have multiple problems. For example data is clearly a Rust object that gets dropped at the end of the function. We don't know what data is, but depending on how it is built even this alone can result in a double free when returning to C.

Anyway, if data is OK to be dropped and the problem is only in information.data you can use ManuallyDrop:

let not_dropped = ManuallyDrop::new(unsafe {data.data_as_vec().expect("NULL DATA")});
let mut information = info {
    row : data.row , 
    column : data.column ,
    data :  not_dropped,
};
smth!(&mut information);
1 Like

Sounds right , ill test it

Only if they are passing the vector by reference everywhere, and not calling any functions like push that touch the capacity - in other words, yes, but only when the way they use the Vec is limited to the functionality of a &(mut)[T]. Because if you pass a &mut Vec<T> to a function, the function can reallocate it internally and then you'd be forgetting the wrong thing (and too late).

smth!(&mut information) is suspicious, for instance.

Yep, I don't see any reason for passing info as mutable, given its definition.

I strongly agree that using &[T] is the correct solution.

so basically it does not work and i have no idea why , i have search whole code base for a reason ig

well at first i did test them the same way

What operations do you do on information.data in smth?