[英]Dealloc a pointer(*mut u8)
我使用 alloc function 创建了一个 ptr
let layout = Layout::from_size_align_unchecked(1024 * 8 , align);
println!("Size {}, Align {}", layout.size(), layout.align());
let ptr = alloc(layout);
现在,我已使用 from_raw_parts() 将此 ptr 转换为 Vector。 之后,在使用 forget(vec) 忘记向量后,我使用 ffi 传递这个向量。 之后我从 ffi 收到 ptr、len 和 capacity,然后我想释放 memory。
dealloc(vv.as_mut_ptr(), layout);
在这个用例中使用 delloc 方法是否正确? 我如何验证 memory 确实已分配? 有没有其他方法可以重新分配 memory。
我如何验证 memory 确实已分配?
Rust nightly
支持 LLVM 的asan
功能。 它是一种地址消毒器,可以检查这些东西。
请注意,这仅适用于 Unix,目前不支持 Windows。
要激活它,请安装nightly
工具链。 然后(用于地址解析)安装llvm
:
sudo apt-get install -y llvm
然后你需要做的就是运行它:
RUSTFLAGS="-Z sanitizer=address" cargo +nightly run
例如,运行以下代码会给我:
rustuse std::alloc::{alloc, dealloc, Layout};
fn main() {
type VecElement = u64;
let size = 1024;
let layout = Layout::from_size_align(size * std::mem::size_of::<VecElement>(), 64).unwrap();
let mut my_vec = unsafe {
let layout = Layout::from_size_align_unchecked(layout.size(), layout.align());
println!("Size {}, Align {}", layout.size(), layout.align());
let ptr = alloc(layout) as *mut VecElement;
Vec::<VecElement>::from_raw_parts(ptr, 0, size)
};
my_vec.push(10);
println!("{:?}", my_vec);
unsafe {
let ptr = my_vec.leak().as_mut_ptr() as *mut u8;
// dealloc(ptr, layout)
}
}
Size 8192, Align 64
[10]
=================================================================
==9815==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 8192 byte(s) in 1 object(s) allocated from:
#0 0x5639279f54c7 in posix_memalign /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:145:3
#1 0x563927a42329 in std::sys::unix::alloc::aligned_malloc::ha31ca2931b3311a0 /rustc/40336865fe7d4a01139a3336639c6971647e885c/library/std/src/sys/unix/alloc.rs:97:23
#2 0x563927a42329 in std::sys::unix::alloc::_$LT$impl$u20$core..alloc..global..GlobalAlloc$u20$for$u20$std..alloc..System$GT$::alloc::h8c999cb61b93cc7a /rustc/40336865fe7d4a01139a3336639c6971647e885c/library/std/src/sys/unix/alloc.rs:22:13
#3 0x563927a42329 in __rdl_alloc /rustc/40336865fe7d4a01139a3336639c6971647e885c/library/std/src/alloc.rs:378:13
#4 0x563927a1fe77 in rust_tmp::main::h6751a6125ac6d734 /home/martin/work/rust-tmp/src/main.rs:12:19
#5 0x563927a283ca in core::ops::function::FnOnce::call_once::h3f2ab14fa827b4ba /rustc/40336865fe7d4a01139a3336639c6971647e885c/library/core/src/ops/function.rs:248:5
#6 0x563927a1f764 in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hd3473a8235573380 /rustc/40336865fe7d4a01139a3336639c6971647e885c/library/std/src/rt.rs:145:18
#7 0x563927a3cd9e in core::ops::function::impls::_$LT$impl$u20$core..ops..function..FnOnce$LT$A$GT$$u20$for$u20$$RF$F$GT$::call_once::hcd03e0aeba5cfb12 /rustc/40336865fe7d4a01139a3336639c6971647e885c/library/core/src/ops/function.rs:280:13
#8 0x563927a3cd9e in std::panicking::try::do_call::h2dbc2d91fe9b324b /rustc/40336865fe7d4a01139a3336639c6971647e885c/library/std/src/panicking.rs:492:40
#9 0x563927a3cd9e in std::panicking::try::ha8bdfaa383f0ed33 /rustc/40336865fe7d4a01139a3336639c6971647e885c/library/std/src/panicking.rs:456:19
#10 0x563927a3cd9e in std::panic::catch_unwind::ha58e9af879223892 /rustc/40336865fe7d4a01139a3336639c6971647e885c/library/std/src/panic.rs:137:14
#11 0x563927a3cd9e in std::rt::lang_start_internal::_$u7b$$u7b$closure$u7d$$u7d$::h56456e42fba96b18 /rustc/40336865fe7d4a01139a3336639c6971647e885c/library/std/src/rt.rs:128:48
#12 0x563927a3cd9e in std::panicking::try::do_call::h2bc188e30e56674d /rustc/40336865fe7d4a01139a3336639c6971647e885c/library/std/src/panicking.rs:492:40
#13 0x563927a3cd9e in std::panicking::try::hc5e32e9b04c0821c /rustc/40336865fe7d4a01139a3336639c6971647e885c/library/std/src/panicking.rs:456:19
#14 0x563927a3cd9e in std::panic::catch_unwind::h8f69e6799c52cea0 /rustc/40336865fe7d4a01139a3336639c6971647e885c/library/std/src/panic.rs:137:14
#15 0x563927a3cd9e in std::rt::lang_start_internal::hd1476181c5102217 /rustc/40336865fe7d4a01139a3336639c6971647e885c/library/std/src/rt.rs:128:20
SUMMARY: AddressSanitizer: 8192 byte(s) leaked in 1 allocation(s).
但是,运行解除分配的正确版本会给我:
use std::alloc::{alloc, dealloc, Layout};
fn main() {
type VecElement = u64;
let size = 1024;
let layout = Layout::from_size_align(size * std::mem::size_of::<VecElement>(), 64).unwrap();
let mut my_vec = unsafe {
let layout = Layout::from_size_align_unchecked(layout.size(), layout.align());
println!("Size {}, Align {}", layout.size(), layout.align());
let ptr = alloc(layout) as *mut VecElement;
Vec::<VecElement>::from_raw_parts(ptr, 0, size)
};
my_vec.push(10);
println!("{:?}", my_vec);
unsafe {
let ptr = my_vec.leak().as_mut_ptr() as *mut u8;
dealloc(ptr, layout)
}
}
Size 8192, Align 64
[10]
没有错误。 这表明它确实确实正确地解除了分配。
你正在做的事很危险。 您必须手动确保通过您的dealloc
function 实际释放向量。编译器检查您实际执行此操作的次数为零。 这是一种称为不健全的行为。
可能的解决方案:
Vec
API 的一个健全子集,并确保正确的释放。Vec::new_in()
和Vec::with_capacity_in()
方法。 尽管这确实意味着您的箱子现在需要nightly
编译器。停止! 停止这样做!
向量自动分配和释放 memory,你不需要这些不安全的技巧。
只需使用Vec::new
或Vec::with_capacity
。
let _my_vec = Vec::<u8>::new();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.