繁体   English   中英

释放一个指针(*mut u8)

[英]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::newVec::with_capacity

let _my_vec = Vec::<u8>::new();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM