【问题标题】:How to pass uninitialized variable address in Unsafe Rust如何在 Unsafe Rust 中传递未初始化的变量地址
【发布时间】:2021-01-09 02:55:18
【问题描述】:

以下代码抛出错误

借用可能未初始化的变量:ires

pub fn new(t: QueryType) -> QueryObject
{
    unsafe {
        let mut ires: u32;
        gl::GenQueries(1, &mut ires as *mut u32);
        
        let res = QueryObject {
            index: ires,
            qtype: t as u32,
            status: QueryStatus::Inactive as u32,
        };

        return res;
    }
}

如何在不初始化变量ires的情况下传递变量地址

【问题讨论】:

  • 没有任何东西期望得到未初始化的内存,所以如果你要传递它,你必须非常小心。将其初始化为0 可能会更好。

标签: rust


【解决方案1】:

理想情况下,这是因为 Rust 不能保证 gl::GenQueries() 在初始化之前不会尝试从 ires 读取。因此,您必须始终在尝试借用之前进行初始化。

要解决此问题,您只需使用0 对其进行初始化。您还可以将&mut ires as *mut u32 简化为&mut ires

let mut ires: u32 = 0;
gl::GenQueries(1, &mut ires);

即使您能够绕过“借用可能未初始化的变量”。然后您随后将收到“使用可能未初始化的变量”。因为无法保证 gl::GenQueries() 已初始化 ires

初始化u32 的成本可以忽略不计。但是,如果您坚持,请查看MaybeUninit

【讨论】:

    【解决方案2】:

    您可以使用MaybeUninit 告诉编译器一个值的位模式可能不是有效的位模式。

    let ires = std::mem::MaybeUninit::uninit();
    gl::GenQueries(1, ires.as_mut_ptr());
    let ires = unsafe { ires.assume_init() };
    

    通过使用assume_init,您告诉编译器您已检查ires 是一个有效的初始化值。如果您不这样做,可能会发生未定义的行为。在这种情况下,如果您确定 100% gl::GenQueries 不会尝试读取此值,则给它未初始化的内存应该就可以了。我说“应该”是因为still a debate 未初始化的整数是否为有效整数。

    小心未初始化的内存。如果你想玩它,我建议你看看这个blog post

    【讨论】:

    • “如果你不这样做,可能会发生未定义的行为”。 uninit().assume_init() 未定义的行为。
    • @IbraheemAhmed 只要您从未读取过该值,就不会。如果函数从未真正读取过它并且只是初始化它(不使用&mut ,那会降低值),我认为它是合理的。
    • AFAIK,还没有决定。最好在初始化完成后才调用assume_init,即使是原语。
    • 已修复。 .as_mut_ptr() 函数实际上是我正在寻找的。现在代码是100%,只要gl::getQueries正确初始化ires
    • 这是很多代码,为了节省 1 个时钟周期,用于已经很少调用的东西:)
    猜你喜欢
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    • 2023-03-06
    • 2020-11-26
    • 2017-02-16
    • 1970-01-01
    相关资源
    最近更新 更多