小编Zhi*_* Ma的帖子

假设两个可变引用都不能别名,Rust编译器为什么不优化代码?

据我所知,引用/指针别名会阻碍编译器生成优化代码的能力,因为它们必须确保在两个引用/指针确实是别名的情况下,生成的二进制文件的行为正确。例如,在以下C代码中,

void adds(int  *a, int *b) {
    *a += *b;
    *a += *b;
}
Run Code Online (Sandbox Code Playgroud)

clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)-O3标志编译时,它发出

0000000000000000 <adds>:
   0:    8b 07                    mov    (%rdi),%eax
   2:    03 06                    add    (%rsi),%eax
   4:    89 07                    mov    %eax,(%rdi)  # The first time
   6:    03 06                    add    (%rsi),%eax
   8:    89 07                    mov    %eax,(%rdi)  # The second time
   a:    c3                       retq
Run Code Online (Sandbox Code Playgroud)

下面的代码存回(%rdi)两次的情况下,int *aint *b别名。

当我们明确告诉编译器这两个指针不能使用restrict关键字别名时:

void adds(int * restrict a, int * restrict …
Run Code Online (Sandbox Code Playgroud)

compiler-optimization rust llvm-codegen

268
推荐指数
1
解决办法
3万
查看次数

C++20 的内存模型与 C++11 的内存模型有何不同?

C++11 引入了一种新的内存模型,让“运行”C++11 代码的抽象机器有关于多线程的概念。它还引入了一组内存顺序,内存加载/存储操作遵循这些顺序。

C++20 的维基百科页面说它有

修改后的内存模型。

它给出的参考资料说 C++11 的内存模型有许多缺陷,C++20 将对其进行修改。

有人可以举例说明 C++11 的内存模型带来的问题,以及 C++20 中的问题如何解决吗?

相关问题: C++11的内存模型介绍

c++ c++11 c++20

25
推荐指数
1
解决办法
822
查看次数

为什么 Rust 编译器在移动对象后不重用堆栈上的内存?

我认为一旦一个对象被移动,它在堆栈上占用的内存可以被重用于其他目的。但是,下面的最小示例显示了相反的情况。

#[inline(never)]
fn consume_string(s: String) {
    drop(s);
}

fn main() {
    println!(
        "String occupies {} bytes on the stack.",
        std::mem::size_of::<String>()
    );

    let s = String::from("hello");
    println!("s at {:p}", &s);
    consume_string(s);

    let r = String::from("world");
    println!("r at {:p}", &r);
    consume_string(r);
}
Run Code Online (Sandbox Code Playgroud)

使用--release标志编译代码后,它在我的计算机上提供以下输出。

String occupies 24 bytes on the stack.
s at 0x7ffee3b011b0
r at 0x7ffee3b011c8
Run Code Online (Sandbox Code Playgroud)

很明显,即使s被移动,r也不会重用最初属于 的堆栈上的 24 字节块s。我认为重用移动对象的堆栈内存是安全的,但为什么 Rust 编译器不这样做呢?我错过了任何角落案例吗?

更新:如果我s用大括号括起来,r可以重用堆栈上的 24 字节块。

String occupies 24 bytes on …
Run Code Online (Sandbox Code Playgroud)

llvm compiler-optimization rust

14
推荐指数
1
解决办法
408
查看次数

`&amp;mut []` 的生命周期是否在 Rust 的生命周期分析期间被特别处理?

下面的示例代码有些精心设计,但说明了我的主要关注点。代码编译完美。

struct SliceWrapper<'a>(&'a mut[i32]);

impl<'a> SliceWrapper<'a> {
    fn clear(&mut self) {
        self.0 = &mut [];
    }
}

fn main() {
    let slice = &mut [1, 2, 3];
    let mut wrapper = SliceWrapper(slice);
    wrapper.clear();
}
Run Code Online (Sandbox Code Playgroud)

该行self.0 = &mut [];有效,但如果我们查看它们的生命周期,则非常奇怪:对局部变量的引用被分配给self.0,它存在于方法调用之外clear()

更令人困惑的是,如果我将该行更改为self.0 = &mut [0];,那么编译器会向我抛出一个错误:创建一个临时文件,该临时文件在仍在使用时被释放。

所以我猜 Rust 编译器对待生命周期的方式&mut []不同。真的吗?什么是精确的生命周期规则&mut []

rust

7
推荐指数
1
解决办法
193
查看次数

为什么 Rust 中的通用生命周期参数可以专门用于一个对象的两个不相交的生命周期?

在下面的一段代码中,我试图了解通用生命周期参数'a是如何特化的。

struct Wrapper<'a>(&'a i32);

fn foo() {
    let mut r;

    {
        let x = 0;       // the lifetime of x, call it 'x, starts from here |
        r = Wrapper(&x); // 'a parameter in Wrapper is specialized to 'x    |
        drop(r);         //                                                 |
    }                    //  --------------------------------- 'x ends here |         

    {
        let y = 0;       // the lifetime of y, call it 'y, starts from here   |
                         // 'y is distinct from 'x                            |
                         // neither outlives the …
Run Code Online (Sandbox Code Playgroud)

lifetime rust

7
推荐指数
1
解决办法
152
查看次数

非词法生命周期借用检查器会过早释放锁吗?

我读过什么是非词法生命周期?. 使用非词法借用检查器,编译以下代码:

fn main() {
    let mut scores = vec![1, 2, 3];
    let score = &scores[0]; // borrows `scores`, but never used
                            // its lifetime can end here

    scores.push(4);         // borrows `scores` mutably, and succeeds
}
Run Code Online (Sandbox Code Playgroud)

在上面的情况下似乎是合理的,但是当涉及到互斥锁时,我们不希望它过早释放。

在下面的代码中,我想先锁定一个共享结构,然后执行一个闭包,主要是为了避免死锁。但是,我不确定锁是否会过早释放。

use lazy_static::lazy_static; // 1.3.0
use std::sync::Mutex;

struct Something;

lazy_static! {
    static ref SHARED: Mutex<Something> = Mutex::new(Something);
}

pub fn lock_and_execute(f: Box<Fn()>) {
    let _locked = SHARED.lock(); // `_locked` is never used.
                                 // does its lifetime end here?
    f();
}
Run Code Online (Sandbox Code Playgroud)

Rust …

mutex raii rust borrow-checker

6
推荐指数
2
解决办法
475
查看次数

释放模式下安全 Rust 中的有符号整数溢出是否被视为未定义行为?

Rust 在调试和发布模式下以不同的方式处理有符号整数溢出。当它发生时,Rust 在调试模式下会发生恐慌,而在发布模式下默默地执行二进制补码包装。

据我所知,C/C++ 将有符号整数溢出视为未定义行为,部分原因是:

  1. 在 C 标准化的那个时候,表示有符号整数的不同底层体系结构,例如补码,可能仍在某处使用。编译器无法假设硬件中如何处理溢出。
  2. 后来的编译器因此做出假设,例如两个正整数之和也必须为正数才能生成优化的机器代码。

因此,如果 Rust 编译器确实在有符号整数方面执行与 C/C++ 编译器相同类型的优化,那么为什么The Rustonomicon指出:

无论如何,Safe Rust 不会导致未定义行为。

或者即使 Rust 编译器不执行这样的优化,Rust 程序员仍然不希望看到有符号整数环绕。不能称为“未定义行为”吗?

integer-overflow rust llvm-codegen

5
推荐指数
1
解决办法
1070
查看次数

`UnsafeCell` 是 Rust 中的编译器优化障碍吗?

不安全代码指南参考中,它说

Rust 中的所有内部突变都必须发生在 内部UnsafeCell,因此所有具有内部可变性的数据结构都必须(直接或间接)用于UnsafeCell此目的。

另外,在关于 的讨论UnsafeCell中,它说

UnsafeCell基本上是编译器的优化障碍。

确实如此UnsafeCell是 Rust 中的编译器优化障碍吗?如果是,标准库源代码中的哪一行发出了屏障,它是如何工作的?

[更新]

相关问题的答案给出了非常好的解释。TL;DR 版本是:UnsafeCell<T>被标记为#[lang = "unsafe_cell"]强制它在以下情况下保持不变T

现在我认为这与优化没有太大关系,但与寿命分析的相互作用更密切。

对于 Rust 中的方差概念,The Rustonomicon Book给出了详细的解释。

rust

5
推荐指数
0
解决办法
478
查看次数

为什么通过指向移动变量的指针写入在 Rust 中没有被确定为 UB?

我正在调查阻止 Rust 编译器优化某些代码片段的可能原因。我在 rust-lang 的一个 issue 中发现了这条评论,它提醒了我。

我们不能优化可变借用的局部变量的存储,因为正如@matthewjasper 在 #61430 中指出的那样,并没有决定以下是 UB:

let mut x = String::new();
let p = &mut x as *mut String;
let y = x;
p.write(String::new());
Run Code Online (Sandbox Code Playgroud)

我认为x当它移动到y. p.write()通过时晃来晃去。但为什么这不决定为UB?

undefined-behavior rust

5
推荐指数
1
解决办法
106
查看次数

如何在Rust中将String与String进行匹配?

我想决定一个字符串是否以Rust中的另一个字符串开头。

我看到了类似的问题,要求在Rust中将String与文字字符串匹配,但这在这里不起作用。例如,在以下代码中,

fn main() {
    let a = String::from("hello world!");
    let b = String::from("hello");
    a.starts_with(b);
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨:

fn main() {
    let a = String::from("hello world!");
    let b = String::from("hello");
    a.starts_with(b);
}
Run Code Online (Sandbox Code Playgroud)

我可以手动实现简单的功能,但这就是重新实现轮子。如何在Rust中很好地完成此工作?

string match rust

2
推荐指数
1
解决办法
95
查看次数