为什么 Rust 不允许可变别名?

2023-12-09

Rust 不允许这种代码,因为它不安全:

fn main() {
    let mut i = 42;
    let ref_to_i_1 = unsafe { &mut *(&mut i as *mut i32) };
    let ref_to_i_2 = unsafe { &mut *(&mut i as *mut i32) };

    *ref_to_i_1 = 1;
    *ref_to_i_2 = 2;
}

我怎么能做坏事(e.g.分段错误、未定义的行为等)以及对同一事物的多个可变引用?

我能看到的唯一可能的问题来自数据的生命周期。在这里,如果i还活着,对它的每个可变引用都应该没问题。

我可以看到引入线程时可能会出现问题,但为什么即使我在一个线程中完成所有操作,它也会被阻止?


C++ 程序(甚至 Java 程序)中一个非常常见的陷阱是在迭代集合时修改集合,如下所示:

for (it: collection) {
    if (predicate(*it)) {
        collection.remove(it);
    }
}

对于 C++ 标准库集合,这会导致未定义的行为。也许迭代会一直工作,直到到达最后一个条目,但最后一个条目将取消引用悬空指针或读取数组的末尾。也许集合底层的整个数组将被重新定位,并且它会立即失败。也许它在大多数情况下都有效,但如果在错误的时间发生重新分配,则会失败。在大多数 Java 标准集合中,根据语言规范,这也是未定义的行为,但集合往往会抛出异常ConcurrentModificationException- 即使您的代码正确,也会导致运行时成本的检查。这两种语言都无法在编译过程中检测到错误。

这是并发引起的数据争用的常见示例,即使在单线程环境中也是如此。并发不仅仅意味着并行性:它还意味着嵌套计算。在 Rust 中,这种错误是在编译期间检测到的,因为迭代器对集合具有不可变的借用,因此在迭代器处于活动状态时无法更改集合。

一个更容易理解但不太常见的示例是向函数传递多个指针(或引用)时的指针别名。一个具体的例子是将重叠的内存范围传递给memcpy代替memmove。实际上,Rust's memcpy相等的 is unsafe也是如此,但那是因为它需要指针而不是引用。链接页面显示了如何制作一个安全的swap使用可变保证的函数参考从来没有别名。

引用别名的一个更人为的示例如下:

int f(int *x, int *y) { return (*x)++ + (*y)++; }
int i = 3;
f(&i, &i); // result is undefined

您无法在 Rust 中编写类似的函数调用,因为您必须对同一变量进行两次可变借用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Rust 不允许可变别名? 的相关文章

随机推荐

  • 适用于 Android 的 catmull-rom 样条线

    我正在尝试找到一种在android平台上实现catmull rom样条线的方法 以便通过n个点平滑地绘制一条线 理想情况下 我能够通过 Path 及其cubicTo 方法调整三次贝塞尔曲线 如本线程中提到的 如何在 Android 中通过树
  • 如何列出目录中的所有子目录

    我正在开发一个项目 我需要列出目录中的所有子目录 例如 如何列出驱动器 C 中的所有子目录 Use Directory GetDirectories获取指定目录的子目录 你的目录路径 结果是一个字符串数组 var directories D
  • 我怎样才能忽略超类?

    我正在尝试编写一个网络服务java util loggingAPI 所以我写了一个继承自LogRecord的类MyLogRecord 我用JAX B注释对这个类进行了注释 包括 XmlAccessorType XmlAccessType N
  • 从纬度、经度转换为 x、y

    我想将 GPS 位置 纬度 经度 转换为 x y 坐标 我找到了很多关于这个主题的链接并应用了它 但它没有给我正确的答案 我按照以下步骤来测试答案 1 首先 我取两个位置并使用地图计算它们之间的距离 2 然后将这两个位置转换为x y坐标 3
  • 如何在 Django 中设置自定义中间件?

    我正在尝试创建一个中间件 以选择性地将 kwarg 传递给满足条件的每个视图 问题是我找不到如何设置中间件的示例 我见过重写我想要的方法的类 process view Class CheckConditionMiddleware objec
  • jpa如何创建与父实体具有相同id的新实体(联合继承)

    我的问题非常类似于更改保留其 ID 的实体的类型 但我使用 InheritanceType JOINED 而不是 Table per class 这意味着我不更改任何表 只是创建一个新的子类 其 id 与超类相同 总而言之 我有一个 Per
  • 如何在用户表单列表框中显示过滤后的行

    我在用户窗体中有一个 Excel 工作表和一个列表框 当我通过单击用户窗体上的按钮来过滤工作表并更新列表框时 我会看到列表框中的所有行 我的意思是 listbox1 显示所有单元格 过滤器 无过滤器 我的更新列表框的代码 Private S
  • 组合框控件模板下拉按钮

    我想知道是否有人有一个示例 说明如何设置组合框的样式 模板以仅在默认初始状态下显示按钮 有点像功能区栏的 DropDownButton 库 我只希望用户能够单击按钮并列出组合框项目 做出选择后 它不会将所选项目保存在文本字段中 因为没有文本
  • h2o 模型列出每个特征的 dtypes

    有没有一种方法可以列出现有 h2o 模型的每个特征的预期数据类型 而无需查看训练数据 类似于的输出h2o frame types 但不查看训练数据 只查看模型对象 在本例中 我有一个已保存的模型文件 可以导入回 h2o 的通用类型 而不是
  • HTTPS 通信失败 ABAP

    我正在开发一个应连接到两个 Web 应用程序的应用程序 第一个 Web 应用程序已完成 http example com 不幸的是 第二个 Web 应用程序使用 HTTPS https example com 抛出这个错误 Http Com
  • Android java使用Comparable自定义排序

    Override public int compareTo final myRow another final int BEFORE 1 final int EQUAL 0 final int AFTER 1 if this another
  • 如何使用 matplotlib 在单个页面上绘制多个绘图?

    我编写了一次打开 16 个数字的代码 目前 它们都作为单独的图表打开 我希望他们在同一页面上打开所有内容 不是同一个图表 我想要在单个页面 窗口上显示 16 个独立的图表 此外 由于某种原因 numbins 和 defaultreallim
  • 按类别名称搜索

    当我尝试按类别名称进行搜索时 它什么也没有返回 例如 我有有机 独特 体育等类别 在搜索中我输入独特 但我没有得到任何结果 不幸的是 Magento 的默认搜索功能是产品搜索 并且仅限于该范围 当您搜索 Unique 时 它会查找产品名称
  • Reporting Services 表达式在某些情况下会出错

    在报告的摘要行中计算平均值时出现错误 我的表情是这样的 IIF SUM Fields column3 Value gt 0 Format DateAdd s SUM Fields column4 Value SUM Fields colum
  • 在pygame中检查歌曲是否播放完毕

    有什么方法可以判断 pygame 中的歌曲是否已播放完毕 这是代码 from tkinter import import pygame root Tk pygame init def play pygame mixer music load
  • Visual Studio 2010 局部变量历史记录

    我正在调试一个具有多个嵌套循环的进程 这些循环会更改几个不同的局部变量 我可以通过一次迭代一次来观看这些内容 但这非常乏味 而且我正在忘记自己的位置 我根本没有时间每次都记下每个变量 有没有办法可以查看局部变量的历史记录 一个插件 如果没有
  • 在 xsl 变量中存储 html 标签

    抱歉 如果这是一个愚蠢的问题 但是可以在 xsl 1 0 变量中存储和检索 HTML 片段吗 例如
  • 在 Vagrant 配置期间使用 Sed 将行追加到文件

    我目前正在使用Vagrant设置运行 Ubuntu 的开发机器 我想在我的中添加几行 profile将目录添加到我的 PATH变量 使用sed 为此 我将这些行添加到我的机器中Vagrantfile config vm provision
  • 左值整型常量表达式是常量表达式吗?

    N4527 5 20 表达式常量 p3 An 积分常量表达式是整型或无范围枚举类型的表达式 隐式转换为纯右值 其中转换后的表达式是核心常量表达式 5 20 expr const p5 A 常量表达式是一个泛左值核心常量表达式 其值引用作为常
  • 为什么 Rust 不允许可变别名?

    Rust 不允许这种代码 因为它不安全 fn main let mut i 42 let ref to i 1 unsafe mut mut i as mut i32 let ref to i 2 unsafe mut mut i as m