Rust入门(十四):不安全Rust

这篇具有很好参考价值的文章主要介绍了Rust入门(十四):不安全Rust。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

不安全Rust

Rust 可以不强制执行内存安全保证,这被称为 不安全 Rustunsafe Rust),这类代码会提供额外的超能力。

可以通过 unsafe 关键字来切换到不安全 Rust,接着可以开启一个新的存放不安全代码的块,有五类可以在不安全 Rust 中进行而不能用于安全 Rust 的操作:

  • 解引用裸指针
  • 调用不安全的函数或方法
  • 访问或修改可变静态变量
  • 实现不安全 trait
  • 访问 union 的字段

解引用裸指针

不安全 Rust 有两个被称为 裸指针raw pointers)的类似于引用的新类型。和引用一样,裸指针是不可变或可变的,分别写作 *const T*mut T。这里的星号不是解引用运算符;它是类型名称的一部分。在裸指针的上下文中,不可变 意味着指针解引用之后不能直接赋值。

裸指针与引用和智能指针的区别在于

  • 允许忽略借用规则,可以同时拥有不可变和可变的指针,或多个指向相同位置的可变指针
  • 不保证指向有效的内存
  • 允许为空
  • 不能实现任何自动清理功能
let mut num = 5;
let r1 = &num as *const i32;
let r2 = &mut num as *mut i32;

可以在安全代码中 创建 裸指针,只是不能在不安全块之外 解引用 裸指针,稍后便会看到。使用 as 可以将不可变和可变引用强转为对应的裸指针类型

let address = 0x012345usize;
let r = address as *const i32;

现在我们要做的就是对裸指针使用解引用运算符 *,这需要一个 unsafe 块,创建一个指针不会造成任何危险;只有当访问其指向的值时才有可能遇到无效的值:

let r1 = &num as *const i32;
let r2 = &mut num as *mut i32;
unsafe {
    println!("r1 is: {}", *r1);
    println!("r2 is: {}", *r2);
}

调用不安全方法

不安全函数和方法与常规函数方法十分类似,除了其开头有一个额外的 unsafe

unsafe fn dangerous() {}
unsafe {
    dangerous();
}

仅仅因为函数包含不安全代码并不意味着整个函数都需要标记为不安全的。例如:标准库中的函数,split_at_mut,它获取一个 slice 并从给定的索引参数开始将其分为两个 slice,slice::from_raw_parts_mut 函数是不安全的因为它获取一个裸指针,并必须确信这个指针是有效的,所以需要包含在 unsafe 块中,但是无需将 split_at_mut 函数的结果标记为 unsafe,并可以在安全 Rust 中调用此函数。

use std::slice;

fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
    let len = slice.len();
    let ptr = slice.as_mut_ptr();

    assert!(mid <= len);

    unsafe {
        (
            slice::from_raw_parts_mut(ptr, mid),
            slice::from_raw_parts_mut(ptr.add(mid), len - mid),
        )
    }
}

extern

有时你的 Rust 代码可能需要与其他语言编写的代码交互。为此 Rust 有一个关键字,extern,有助于创建和使用 外部函数接口Foreign Function Interface, FFI)。extern 块中声明的函数在 Rust 代码中总是不安全的。因为其他语言不会强制执行 Rust 的规则且 Rust 无法检查它们。如下的例子是:集成 C 标准库中的 abs 函数

extern "C" {
    fn abs(input: i32) -> i32;
}

fn main() {
    unsafe {
        println!("Absolute value of -3 according to C: {}", abs(-3));
}

也可以使用 extern 来创建一个允许其他语言调用 Rust 函数的接口。不同于 extern 块,就在 fn 关键字之前增加 extern 关键字并指定所用到的 ABI。还需增加 #[no_mangle] 注解来告诉 Rust 编译器不要 mangle 此函数的名称。一旦其编译为动态库并从 C 语言中链接,call_from_c 函数就能够在 C 代码中访问:

#[no_mangle]
pub extern "C" fn call_from_c() {
    println!("Just called a Rust function from C!");
}

访问修改静态变量

全局变量在 Rust 中被称为 静态static)变量,静态变量中的值有一个固定的内存地址。使用这个值总是会访问相同的地址。另一方面,常量则允许在任何被用到的时候复制其数据

static HELLO_WORLD: &str = "Hello, world!";

fn main() {
    println!("name is: {}", HELLO_WORLD);
}

访问和修改可变静态变量都是不安全的,如下:我们使用 mut 关键来指定可变性。任何读写 COUNTER 的代码都必须位于 unsafe 块中。

static mut COUNTER: u32 = 0;

fn add_to_count(inc: u32) {
    unsafe {
        COUNTER += inc;
    }
}

fn main() {
    add_to_count(3);

    unsafe {
        println!("COUNTER: {}", COUNTER);
    }
}

不安全trait

当 trait 中至少有一个方法中包含编译器无法验证的不变式(invariant)时 trait 是不安全的。可以在 trait 之前增加 unsafe 关键字将 trait 声明为 unsafe,同时 trait 的实现也必须标记为 unsafe,例如:如果实现了一个包含一些不是 SendSync 的类型,比如裸指针,并希望将此类型标记为 SendSync,则必须使用 unsafe

unsafe trait Foo {
    // methods go here
}

unsafe impl Foo for i32 {
    // method implementations go here
}

fn main() {}

访问联合体

unionstruct 类似,但是在一个实例中同时只能使用一个声明的字段,也就是说,一个生命了多个字段的联合体,在使用的时候只能成为其中的一个字段类型,可以查看 参考文档 了解有关联合体的更多信息。

联合体主要用于和 C 代码中的联合体交互。访问联合体的字段是不安全的,因为 Rust 无法保证当前存储在联合体实例中数据的类型。文章来源地址https://www.toymoban.com/news/detail-504195.html

到了这里,关于Rust入门(十四):不安全Rust的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【跟小嘉学 Rust 编程】十四、关于 Cargo 和 Crates.io

    【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学 Rust 编程】六、枚举

    2024年02月11日
    浏览(51)
  • 湖仓一体电商项目(十四):实时任务执行流程

    文章目录 实时任务执行流程 一、准备环境 二、启动Flink代码

    2024年02月03日
    浏览(44)
  • 强制退出hdfs安全模式

    情况: Hbase启动失败 友人说是进入了安全模式,执行 hdfs dfsadmin -safemode leave命令,正常退出失败 == Safe mode ON 启动强制退出: hdfs dfsadmin -safemode forceExit == Safe mode OFF 扩展: safemode 后面可以接 enter 进入安全模式 get 获取安全模式的状态 leave 退出安全模式 forceExit 强制退出安全模式 w

    2024年02月03日
    浏览(43)
  • rust学习-同时执行多Future

    只用 .await 来执行future,会阻塞并发任务,直到特定的 Future 完成 可事实上为什么都是res1完成后再执行res2? join! 不保证并发执行,难道只负责同步等待? 不必在 get_book 完成后再 get_music 返回 Result 的 future,考虑使用 try_join! 而非 join join 只会在所有子 future 都完成后才会完成

    2024年02月13日
    浏览(35)
  • 可以自己实现的Python小游戏,共十四个可收藏可直接拿走~

    今天给大家带来14个py小游戏如:吃金币、打乒乓、滑雪、并夕夕版飞机大战、打地鼠、小恐龙、消消乐、俄罗斯方块、贪吃蛇、24点小游戏、平衡木、外星人入侵、贪心鸟、井字棋888‘’,文章都带了源码,感兴趣的小伙伴感快收藏起来吧 源码分享: 源码分享: 源码分享:

    2024年03月10日
    浏览(51)
  • 【微服务部署】05-安全:强制HTTPS

    互联网发展中,安全是非常重要的,由其是现在HTTPS非常普及的情况下,应用程序在公网上一般都会被强制要求HTTPS。 Ingress强制HTTPS 应用强制HTTPS Ingress强制HTTPS,在Ingress中设置即可. 应用强制HTTPS,当应用程序识别到用户使用的是HTTP协议访问时,强制跳转至HTTPS。这种场景一般

    2024年02月11日
    浏览(35)
  • Rust 构建开源 Pingora 框架可以与nginx媲美

    Cloudflare 为何弃用 Nginx,选择使用 Rust 重新构建新的代理 Pingora 框架。Cloudflare 成立于2010年,是一家领先的云服务提供商,专注于内容分发网络(CDN)和分布式域名解析。它提供一系列安全和性能优化服务,包括防火墙、DDoS防护、SSL/TLS加密和威胁分析。 Pingora 是一个基于 R

    2024年03月15日
    浏览(41)
  • Rust 性能优化 : Rust 性能优化技巧,提升 Rust 程序的执行效率和资源利用率 The Rust Performance

    作者:禅与计算机程序设计艺术 在过去的几年中,随着编程语言的快速发展,编程人员已经逐渐从依赖编译型语言转向了使用解释型语言。相对于编译型语言来说,解释型语言具有更快的执行速度,在某些情况下甚至可以实现接近编译器的运行时效率。但是另一方面,这些语

    2024年02月07日
    浏览(101)
  • 国家强制性灯具安全标准GB7000.1-2015

    随着LED技术的持续发展,很多LED产品逐渐替代了使用传统光源产品的市场。我国现行的灯具国家通用标准仍为GB7000.1-2007版,本次GB7000.1-2015,增加了许多适应LED灯具的要求,这对我国LED灯具产品的认证检测、国际互认起到了很大的作用。 GB7000.1-2015版标准于2015.12.31发布,于2

    2024年02月04日
    浏览(51)
  • Linux可以执行bat吗?

    可以 1.bat是批处理文件,在windows和linux上都可以使用。 2.不过在linux的命令行中不可以直接敲\\\"xxx.bat\\\",系统会去找所有的命令。  3.想要调用bat文件,需要写绝对路径,比如\\\"/home/myDir/xxx.bat\\\",或者是切换到bat文件所在的目录,然后键入:\\\"./xxx.bat\\\".这里的\\\"./\\\"是告诉系统在当前目录下找名为

    2024年02月13日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包