【问题标题】:The initial values of static variables may not even match what’s specified in the source code静态变量的初始值甚至可能与源代码中指定的不匹配
【发布时间】:2022-01-07 10:21:50
【问题描述】:

我正在从事一个围绕嵌入式系统的项目。所以我必须实现一个 alloc 方法来分配一个新的内存段,并实现一个 dealloc 来将过去的分配返回给分配器以供重用。

以下段落摘自 Book Rust for Rustaceans:

在跳转到定义的开始符号之前真正不运行任何代码的平台上,像大多数嵌入式设备一样,静态变量的初始值甚至可能与源代码中指定的值不匹配。在这种情况下,您的初始化函数将需要使用程序二进制文件中指定的初始数据值显式初始化各种静态内存段。

我遇到的问题与上一段完全相同。在运行时,Rust 分配了一个非常大的堆内存。有没有人可以解决这个问题?

此代码适用于 Linux,但不适用于我的设备。因为 Rust 对内存的请求远远大于我设备的容量。

pub struct Heap {
    pub vector: Vec<u8>,
}

pub static mut MY_HEAP: Option<Heap> = None;

fn main() {
    unsafe {
        MY_HEAP = Some(Heap {
            vector: vec![1, 2, 3],
        })
    };
    unsafe {
        match &mut MY_HEAP {
            Some(h) => {
                println!("{:?}", h.vector);
            }
            None => (),
        }
    }
}

你可以在下面看到分配器的实现:

#![feature(allocator_api)]
#![feature(alloc_error_handler)]
#![no_std]
#![crate_name = "ql_alloc"]
#![crate_type = "rlib"]

use ql_sys as ql;
use core::alloc::{GlobalAlloc, Layout};
pub struct QLAllocator;

unsafe impl GlobalAlloc for QLAllocator {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        let a = ql::Ql_MEM_Alloc(layout.size() as u32) as *mut u8;
        a
    }
    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
        ql::Ql_MEM_Free(ptr as *mut _ as *mut cty::c_void);
    }
}

#[alloc_error_handler]
fn on_oom(layout: Layout) -> ! {
    loop {}
}

【问题讨论】:

  • 您能否澄清一下给出的代码不能按预期工作?
  • 这不能回答我的问题。 OOM 问题与静态初始化有什么关系?
  • 你为什么认为这些事情是相关的?在我的脑海中,如果MY_HEAP 未初始化,您需要使用ptr::write 而不是= 对其进行初始化,但该错误将表现为虚假的free,而不是OOM。
  • 您可以将assert!(MY_HEAP.is_none()) 添加到main() 的开头并查看断言是否跳闸。如果断言通过,则您的静态已正确初始化。 Trent 的解决方案意味着您的问题不在您认为的位置,您应该检查分配器接收到的内容并返回以对其进行调试。也许您的分配库没有正确初始化?

标签: rust allocation rust-no-std


【解决方案1】:

我将MY_HEAP = Some(...) 替换为core::ptr::write(&amp;mut MY_HEAP, Some(...)),问题已解决。

pub struct Heap {
    pub vector: Vec<u8>,
}

pub static mut MY_HEAP: Option<Heap> = None;

fn main() {
    unsafe {
        assert!(MY_HEAP.is_none());
    }
    unsafe {
        core::ptr::write(
            &mut MY_HEAP,
            Some(Heap {
                vector: vec![1, 2, 3],
            }),
        );
    };
    unsafe {
        match &mut MY_HEAP {
            Some(h) => {
                println!("{:?}", h.vector);
            }
            None => (),
        }
    }
}

感谢 trent ᶠᵒʳᵐᵉʳˡʸ ᶜˡ

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-08
    • 2020-06-23
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多