本文介绍了为什么Rust不允许可变别名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

Rust禁止这种代码,因为它是不安全的:

Rust disallows this kind of code because it is unsafe:

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;
}

如何通过对同一事物进行多个可变引用来做不好的事情(例如, 分段错误,未定义的行为等)?

How can I do do something bad (e.g. segmentation fault, undefined behavior, etc.) with multiple mutable references to the same thing?

我只能看到的唯一问题来自数据的生存期.在这里,如果i仍然存在,则对它的每个可变引用都应该可以.

The only possible issues I can see come from the lifetime of the data. Here, if i is alive, each mutable reference to it should be ok.

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

I can see how there might be problems when threads are introduced, but why is it prevented even if I do everything in one thread?

推荐答案

我相信,尽管您这样做会触发未定义的行为",但技术上 noalias标志尚未被Rust编译器使用,所以实际上现在,您实际上可能无法以这种方式触发未定义的行为,您要触发的是实现特定行为",即根据LLVM的行为类似于C ++".

I believe that although you trigger 'undefined behavior' by doing this, technically the noalias flag is not used by the Rust compiler yet, so practically speaking, right now, you probably can't actually trigger undefined behavior this way, what you're triggering is 'implementation specific behavior', which is 'behaves like C++ according to LLVM'.

存在跟踪问题.

已阅读这一系列有关未定义行为的博客文章

在我看来,竞争条件(例如迭代器)并不是您所谈论内容的一个很好的例子;在单线程环境中,如果小心的话,可以避免此类问题.这与创建指向无效内存的任意指针并对其进行写入没有什么不同.只是不做.您不会比使用C更糟糕.

In my opinion, race conditions (like iterators) aren't really a good example of what you're talking about; in a single threaded environment you can avoid that sort of problem if you're careful. This is no different to creating an arbitrary pointer to invalid memory and writing to it; just don't do it. You're no worse off than using C.

要了解此处的问题,请考虑在发布模式下进行编译时,编译器在执行优化时可能会也可能不会对语句进行重新排序;这意味着尽管您的代码可以按线性顺序运行:

To understand the issue here, consider when compiling in release mode the compiler may or may not reorder statements when optimizations are performed; that means that although your code may run in the linear sequence:

a; b; c;

不能保证编译器在运行时将按该顺序执行它们,如果(根据编译器所知道的)逻辑上没有理由必须以特定的原子顺序执行语句.我上面链接到的博客的第3部分演示了这如何导致未定义的行为.

There is no guarantee the compiler will execute them in that sequence when it runs, if (according to what the compiler knows), there is no logical reason that the statements must be performed in a specific atomic sequence. Part 3 of the blog I've linked to above demonstrates how this can cause undefined behavior.

tl; dr :基本上,编译器可以执行各种优化;当且仅当您的程序未触发未定义的行为时,这些保证可以继续使您的程序以确定性的方式运行.

tl;dr: Basically, the compiler may perform various optimizations; these are guaranteed to continue to make your program behave in a deterministic fashion if and only if your program does not trigger undefined behavior.

据我所知,Rust编译器当前并没有使用许多可能导致这种故障的高级优化",但不能保证它不会在未来.引入新的编译器优化并不是一个重大变化".

As far as I'm aware the Rust compiler currently doesn't use many 'advanced optimizations' that may cause this kind of failure, but there is no guarantee that it won't in the future. It is not a 'breaking change' to introduce new compiler optimizations.

因此...实际上,您现在极不可能仅通过可变别名来触发实际的未定义行为;但这种限制使将来有可能进行性能优化.

So... it's actually probably quite unlikely you'll be able to trigger actual undefined behavior just via mutable aliasing right now; but the restriction allows the possibility of future performance optimizations.

相关报价:

任何事情都可能发生;该标准没有任何要求.该程序可能无法编译,或者执行不正确(崩溃或无提示地生成不正确的结果),或者可能偶然地完全按照程序员的意图进行操作.

Anything at all can happen; the Standard imposes no requirements. The program may fail to compile, or it may execute incorrectly (either crashing or silently generating incorrect results), or it may fortuitously do exactly what the programmer intended.

这篇关于为什么Rust不允许可变别名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-06 12:31