不使用UB,使用栈内存作为堆内存
Use stack memory as heap memory without UB
我在无法使用堆内存而只能使用堆栈内存的环境中工作。为了不受 #[no_std]
环境的限制,我尝试将堆栈内存用作 linked-list-allocator 板条箱的堆内存。这是我的方法。
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
x86_64-unknown-linux-gnu
和 rustc
版本 1.49.0-nightly
编译和 运行 以下代码我收到以下错误:
memory allocation of 4 bytes failedAborted (core dumped)
是否有一些 rust 编译器假设我在侵权,或者我对 linked-list-allocator 的使用有误?
编辑:
鉴于 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
}
查看代码并找到看起来很像默认入口点的内容后,我将把我认为是对我的猜测的确认作为答案: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
或其他方式。 “嵌入式”论坛 / 讨论 / ... 可能更有帮助,因为那真的不是我接触过的东西。
我在无法使用堆内存而只能使用堆栈内存的环境中工作。为了不受 #[no_std]
环境的限制,我尝试将堆栈内存用作 linked-list-allocator 板条箱的堆内存。这是我的方法。
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
x86_64-unknown-linux-gnu
和 rustc
版本 1.49.0-nightly
编译和 运行 以下代码我收到以下错误:
memory allocation of 4 bytes failedAborted (core dumped)
是否有一些 rust 编译器假设我在侵权,或者我对 linked-list-allocator 的使用有误?
编辑: 鉴于 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
}
查看代码并找到看起来很像默认入口点的内容后,我将把我认为是对我的猜测的确认作为答案: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
或其他方式。 “嵌入式”论坛 / 讨论 / ... 可能更有帮助,因为那真的不是我接触过的东西。