Vector – what is the correct way to convert VEC to FFI without reallocation?

I need to pass an element VEC in the FFI Through the experiment, I found some interesting ideas I started to give the FFI all 3: PTR, len and capacity so that I could rebuild VEC and destroy it later:

let ptr = vec.as_mut_ptr();
let len = vec.len();
let cap = vec.capacity();
mem::forget(vec);
extern_fn(ptr,len,cap);

// ...

pub unsafe extern "C" fn free(ptr: *mut u8,len: usize,cap: usize) {
    let _ = Vec::from_raw_parts(ptr,cap);
}

I want to get rid of capacity because it's useless for my front end; It's just so that I can reconstruct my vector to release my memory

Vec :: shrink_ to_ Fit () is attractive because it seems to eliminate the need for processing capacity Unfortunately, the documentation above it does not guarantee that it will make len = = capacity, so I assume that it is in from_ raw_ Undefined behavior may be triggered during parts()

into_@ R_ 42_ 2419@ed_slice () seems to have a guarantee that it will get len = = capacity from docs, so I'll use it next If I am wrong, please correct me The problem is that it does not seem to guarantee against redistribution This is a simple procedure:

fn main() {
    let mut v = Vec::with_capacity(1000);
    v.push(100u8);
    v.push(110);
    let ptr_1 = v.as_mut_ptr();
    let mut @R_42_2419@ed_slice = v.into_@R_42_2419@ed_slice();
    let ptr_2 = @R_42_2419@ed_slice.as_mut_ptr();
    let ptr_3 = @R_42_2419@::into_raw(@R_42_2419@ed_slice);
    println!("{:?}. {:?}. {:?}",ptr_1,ptr_2,ptr_3);
}

In the playground, it prints:

rustc 1.14.0 (e8a012324 2016-12-16)
0x7fdc9841b000. 0x7fdc98414018. 0x7fdc98414018

It's bad if you have to find new memory instead of taking off the extra capacity without causing a copy

Is there any other way to pass my vector to FFI (to c) without passing capacity? It seems that into_@ R_ 42_ 2419@ed_slice () is what I need, but why does it involve reallocating and replicating data?

Solution

The reason is relatively simple

Modern memory allocators separate allocations in "size" plates, where each plate is responsible for handling a given range of sizes For example:

>8-byte slab: anything from 1 to 8 bytes > 16 byte slab: anything from 9 to 16 bytes > 24 byte slab: anything from 17 to 24 bytes >

When you allocate memory, you ask for a given size. The allocator finds the correct slab, gets a block from it, and then returns your pointer

When you free memory... How do you expect the allocator to find the right tablet? There are two solutions:

>The allocator has a way to search the board containing your memory range. Somehow, it involves a linear search through the board or some kind of global lookup table or... > tell the allocator what the size of the allocated block is

It is obvious that the C interface (free, realloc) is quite below the standard, so rust wants to use a more effective interface, that is, onus's interface on the caller

So you have two choices:

>Ensure that the length and capacity are equal through capacity >

As you know, (2) new assignments may be required, which is very unpopular (1) It can be realized by transferring capacity all the way, or it can store capacity at a certain time and retrieve it when needed

nothing more. You must evaluate your trade - offs

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>