Rust裸指针的安全性实例讲解

 更新时间:2023年05月11日 14:20:28   作者:GP-Bullet  
裸指针是一个不包含所有权和借用关系的原始指针,它们与常规指针相比没有任何限制和保护措施,这篇文章主要介绍了Rust裸指针的安全性实例,需要的朋友可以参考下
/// @brief 初始化cfs调度器
pub unsafe fn sched_cfs_init() {
    if CFS_SCHEDULER_PTR.is_null() {
        CFS_SCHEDULER_PTR = Box::leak(Box::new(SchedulerCFS::new()));
    } else {
        kBUG!("Try to init CFS Scheduler twice.");
        panic!("Try to init CFS Scheduler twice.");
    }
}

如果CFS_SCHEDULER_PTR是空指针,则创建一个名为SchedulerCFS的新实例,并将其封装到一个Box对象中。然后通过Box::leak()函数将其转换为裸指针(即将其所有权转让给全局指针CFD_SCHEDULER_PTR)。这个操作非常危险,因为裸指针的生命周期并没有明确规定,所以需要注意避免出现内存泄漏或多重释放的问题。

如果CFS_SCHEDULER_PTR不是空指针,则说明调度器已经被初始化过了,不能重复初始化。在这种情况下,我们会通过kBUG!()宏打印一个日志信息,然后通过panic!()函数抛出一个恐慌(即类似于抛出一个异常)。这将导致程序崩溃并终止运行。

裸指针是一个不包含所有权和借用关系的原始指针,它们与常规指针相比没有任何限制和保护措施。在Rust中,为了避免内存安全问题,推荐使用引用和智能指针来管理内存。

如果必须使用裸指针,则需要明确控制它们的生命周期,以避免出现竞争条件或使用无效指针的情况。具体而言,有以下几个注意点:

  • 裸指针通常只在FFI(Foreign Function Interface)调用或编写底层内核代码时使用。
  • 在创建裸指针之前,需要确保所指向的内存块已经被分配,并且在指针的整个生命期内都处于有效状态。
  • 避免多个裸指针共享同一块内存,并确保裸指针的复制和移动操作不会导致资源重复释放或泄漏。
  • 使用unsafe代码块进行包装,以确保编译器无法自动检查这些代码段,以及标记出哪些代码可能涉及到不安全的操作,并提醒开发者注意可能产生的风险。

所有权和借用

在Rust中,所有权和借用是一种内存管理机制,它能够保证程序在编译期间就能检测到内存错误,并防止发生运行时的安全问题。具体而言,当一个值被绑定到一个变量上时,其所有权会转移到该变量所在的作用域中,同时只有在满足借用限制条件的情况下才能访问该值。

相比之下,裸指针并不包含所有权和借用关系,它们只是指向某个地址的原始指针,与其所指向的值之间没有任何关联。这意味着,在使用裸指针时需要开发者自己负责内存的安全性和正确性。

举个例子,假设有一个包含整型数据的数组,我们可以通过以下方式创建一个含有裸指针的函数:

fn main() {
    let array = [1, 2, 3, 4, 5];
    let raw_pointer: *const i32 = &array[0] as *const i32;
}

这里我们定义了一个名为raw_pointer的裸指针,其中&array[0]获取了数组第一个元素的引用,然后将其强制转化为*const i32类型的原始指针。由于裸指针没有所有权和借用关系,因此在创建完raw_pointer后,我们还需要手动控制其生命周期和内存的正确释放。而通过使用引用或智能指针可以避免这些问题。

控制其生命周期和内存的正确释放:

fn main() {
    let array = [1, 2, 3, 4, 5];
    let raw_pointer: *const i32 = &array[0] as *const i32;
    // 创建一个指向同一位置的不可变引用
    let pointer_ref = unsafe { &*raw_pointer };
    // 打印引用值,说明指针操作成功
    println!("Pointer Ref Value: {}", pointer_ref);
    // 手动释放指针内存
    unsafe {
        // 转换回Box类型方便我们确保及时释放内存
        let box_ptr = Box::from_raw(raw_pointer as *mut i32);
        // box_ptr现在拥有从原先的指针获取过来的所有权
        // 这里并没有立即释放内存,因为box_ptr仍然在作用域中
        // Rust会自动在box_ptr离开作用域后执行drop函数,释放内存
        drop(box_ptr);
    }
}

看回最初的代码:修改

static mut CFS_SCHEDULER_PTR: Option<Box<SchedulerCFS>> = None;
pub fn sched_cfs_init() {
    unsafe {
        if CFS_SCHEDULER_PTR.is_none() {
            let scheduler = Box::new(SchedulerCFS::new());
            CFS_SCHEDULER_PTR = Some(scheduler);
        } else {
            kBUG!("Try to init CFS Scheduler twice.");
            panic!("Try to init CFS Scheduler twice.");
        }
    }
}

在上述代码中,我们将CFS_SCHEDULER_PTR的类型改为了Option<Box<SchedulerCFS>>,表示这是一个可空指针。在初始化CFS调度器时,如果CFS_SCHEDULER_PTR还没有被分配,则创建一个新的调度器实例并将其封装在Box中,然后通过Some()将其包装成一个Option。如果CFS_SCHEDULER_PTR已经被分配,则会触发panic。对于裸指针的管理和释放等操作,由Rust编译器自动处理,提高了代码的安全性和可维护性。

到此这篇关于Rust裸指针的安全性实例的文章就介绍到这了,更多相关Rust裸指针内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Tauri 打开本地文件踩坑分析解决

    Tauri 打开本地文件踩坑分析解决

    这篇文章主要为大家介绍了Tauri 打开本地文件踩坑分析解决,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • 一文掌握Rust编程中的生命周期

    一文掌握Rust编程中的生命周期

    在Rust语言中, 每一个引用都有其生命周期, 通俗讲就是每个引用在程序执行的过程中都有其自身的作用域, 一旦离开其作用域, 其生命周期也宣告结束, 值不再有效,这篇文章主要介绍了Rust编程中的生命周期,需要的朋友可以参考下
    2023-11-11
  • rust多样化错误处理(从零学习)

    rust多样化错误处理(从零学习)

    一个优秀的项目,错误处理的优雅性是至关重要的,而rust,anyhow creat是绕不过去的一个,今天我们来研究下,怎么使用它,帮助我们写出更优雅的代码,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2023-11-11
  • Rust生命周期常见误区(中英对照)全面指南

    Rust生命周期常见误区(中英对照)全面指南

    这篇文章主要WEIDJAI 介绍了Rust生命周期常见误区(中英对照)的全面指南,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • Rust字符串字面值的一些经验总结

    Rust字符串字面值的一些经验总结

    字符串有两种表现形式,一种是基本类型,表示字符串的切片,以&str表示,另一种是可变的string类型,下面这篇文章主要给大家介绍了关于Rust字符串字面值的相关资料,需要的朋友可以参考下
    2022-04-04
  • Rust如何进行模块化开发技巧分享

    Rust如何进行模块化开发技巧分享

    Rust模块化,模块化有助于代码的管理和层次逻辑的清晰,本文主要介绍了Rust如何进行模块化开发,结合实例代码给大家讲解的非常详细,需要的朋友可以参考下
    2023-01-01
  • 从迷你todo 命令行入门Rust示例详解

    从迷你todo 命令行入门Rust示例详解

    这篇文章主要为大家介绍了从一个迷你todo命令行入门Rust的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • Rust 累计时间长度的操作方法

    Rust 累计时间长度的操作方法

    在Rust中,如果你想要记录累计时间,通常可以使用标准库中的std::time::Duration类型,这篇文章主要介绍了Rust如何累计时间长度,需要的朋友可以参考下
    2024-05-05
  • 详解Rust中泛型的使用

    详解Rust中泛型的使用

    泛型是一种在编写代码时不指定具体类型,而在使用时再确定类型的编程技巧,本文将详细介绍 Rust 中泛型的相关概念和用法,希望对大家有所帮助
    2023-06-06
  • Rust中的函数指针详解

    Rust中的函数指针详解

    Rust是一种现代的系统编程语言,它支持函数指针。函数指针是指向函数的指针,可以将函数作为参数传递给其他函数或存储在变量中。Rust中的函数指针可以用于实现回调函数、动态分发和多态等功能。本文将介绍Rust中的函数指针的基本用法和高级用法。
    2023-05-05

最新评论