[英]What is an efficient way to reset all values of a Vec<T> without resizing it?
[英]What is the correct way to convert a Vec for FFI without reallocation?
我需要在FFI中傳遞一個元素的Vec
。 通過實驗,我發現了一些有趣的觀點。 我開始給FFI全部3: ptr
, len
和capacity
以便我可以重建Vec
以便以后銷毀它:
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, len, cap);
}
我想擺脫capacity
因為它對我的前端沒用; 它只是為了讓我可以重建我的矢量以釋放記憶。
Vec::shrink_to_fit()
很有吸引力,因為它似乎消除了處理容量的需要。 不幸的是,它上面的文檔並不保證它會使len == capacity
,因此我假設在from_raw_parts()
期間可能會觸發Undefined Behavior。
into_boxed_slice()
似乎保證它將從文檔中獲得len == capacity
,所以我接下來使用它。 如果我錯了,請糾正我 。 問題是它似乎不能保證不重新分配。 這是一個簡單的程序:
fn main() {
let mut v = Vec::with_capacity(1000);
v.push(100u8);
v.push(110);
let ptr_1 = v.as_mut_ptr();
let mut boxed_slice = v.into_boxed_slice();
let ptr_2 = boxed_slice.as_mut_ptr();
let ptr_3 = Box::into_raw(boxed_slice);
println!("{:?}. {:?}. {:?}", ptr_1, ptr_2, ptr_3);
}
在操場上 ,它打印:
rustc 1.14.0 (e8a012324 2016-12-16)
0x7fdc9841b000. 0x7fdc98414018. 0x7fdc98414018
如果必須找到新的內存而不是在不造成副本的情況下脫掉額外的容量,這就不好了。
有沒有其他方法可以將我的矢量傳遞到FFI(到C)而不傳遞容量? 似乎into_boxed_slice()
是我需要的,但為什么它涉及重新分配和復制數據?
原因相對簡單。
現代內存分配器將在“大小”平板中分離分配,其中每個平板負責處理給定范圍的大小。 例如:
當你分配內存時,你要求一個給定的大小,分配器找到正確的slab,從中獲取一個塊,然后返回你的指針。
當你釋放內存時...你怎么期望分配器找到合適的平板? 有兩種解決方案:
這里顯而易見的是,C接口( free
, realloc
)相當低於標准,因此Rust希望使用更有效的接口,即onus在調用者上的接口。
所以,你有兩個選擇:
如您所知,(2)可能需要新的分配,這是非常不受歡迎的。 (1)可以通過全程傳遞容量來實現,也可以在某個時候存儲容量,然后在需要時檢索它。
而已。 你必須評估你的權衡。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.