首页 > 解决方案 > 使用栈内存作为没有UB的堆内存

问题描述

我在一个不能使用堆内存而只能使用堆栈内存的环境中工作。为了不受#[no_std]环境的限制,我尝试将堆栈内存用作链表分配器板条箱的堆内存。这是我的方法。

use linked_list_allocator::LockedHeap;
use std::mem::MaybeUninit;

#[global_allocator]
static ALLOCATOR: LockedHeap = LockedHeap::empty();

pub unsafe fn init_heap(heap_start: usize, heap_size: usize) {
    ALLOCATOR.lock().init(heap_start, heap_size);
}

fn main() {
    const HEAP_SIZE: usize = 2048;
    let mut heap: MaybeUninit<[u8; HEAP_SIZE]> = MaybeUninit::zeroed();
    unsafe { init_heap(heap.as_mut_ptr() as usize, HEAP_SIZE) }
    println!(
        "{} {} {} {} {} {}",
        "This", "String", "Has", "Been", "Dynamically", "Allocated"
    );
}

llvm-target在我的笔记本电脑上使用ofx86_64-unknown-linux-gnu和一个rustc版本编译和运行以下代码,1.49.0-nightly我收到以下错误:

memory allocation of 4 bytes failedAborted (core dumped)

是否存在一些我违反了 rust 编译器的假设或者我对链表分配器的使用错误?

编辑:鉴于Masklinn的回答和评论,这里是一个工作示例:

#![feature(start)]

use linked_list_allocator::LockedHeap;

#[global_allocator]
static ALLOCATOR: LockedHeap = LockedHeap::empty();

pub unsafe fn init_heap(heap_start: usize, heap_size: usize) {
    ALLOCATOR.lock().init(heap_start, heap_size);
}

#[start]
fn main(_argn: isize, _argv: *const *const u8) -> isize {
    const HEAP_SIZE: usize = 2048;
    let mut heap = [0u8; HEAP_SIZE];
    unsafe { init_heap(heap.as_mut_ptr() as usize, HEAP_SIZE) }
    std::mem::forget(heap);

    println!(
        "{} {} {} {} {} {}",
        "This", "String", "Has", "Been", "Dynamically", "Allocated"
    );
    0
}

标签: ruststackheap-memoryallocator

解决方案


在查看代码并找到看起来很像默认入口点之后,我将把我认为是我猜测的确认作为答案:global_allocator 必须在之前完全初始化main,因为默认入口点依赖于它并分配:https ://github.com/rust-lang/rust/blob/master/library/std/src/rt.rs#L40-L45


        // Next, set up the current Thread with the guard information we just
        // created. Note that this isn't necessary in general for new threads,
        // but we just do this to name the main thread and to give it correct
        // info about the stack bounds.
        let thread = Thread::new(Some("main".to_owned()));
        thread_info::set(main_guard, thread);

我首先错过了它并查看了它,sys::args::init但它似乎没有分配(直到你请求std::args::args),但事实证明那里有一个明显的分配,main. 实际上有第二个分配Thread::new(它创建一个Arc)。

所以你将不得不no_std,并且可能alloc直接使用或其他东西。“嵌入式”论坛/讨论/ ...可能在那里更有帮助,因为这真的不是我曾经接触过的东西。


推荐阅读