【发布时间】:2021-08-02 13:35:43
【问题描述】:
我认为一旦一个对象被移动,它在堆栈上占用的内存就可以被重新用于其他目的。但是,下面的最小示例显示了相反的情况。
#[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);
}
使用--release 标志编译代码后,它会在我的计算机上给出以下输出。
String occupies 24 bytes on the stack.
s at 0x7ffee3b011b0
r at 0x7ffee3b011c8
很明显,即使 s 被移动,r 也不会重用堆栈上最初属于 s 的 24 字节块。我认为重用移动对象的堆栈内存是安全的,但为什么 Rust 编译器不这样做呢?我错过了任何角落案例吗?
更新:
如果我用大括号括住s,r 可以重用堆栈上的 24 字节块。
#[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);
}
上面的代码给出了下面的输出。
String occupies 24 bytes on the stack.
s at 0x7ffee2ca31f8
r at 0x7ffee2ca31f8
我认为大括号应该没有任何区别,因为s 的生命周期在调用comsume_string(s) 之后结束,并且它的丢弃处理程序在comsume_string() 中调用。为什么添加大括号会启用优化?
我使用的 Rust 编译器版本如下。
rustc 1.54.0-nightly (5c0292654 2021-05-11)
binary: rustc
commit-hash: 5c029265465301fe9cb3960ce2a5da6c99b8dcf2
commit-date: 2021-05-11
host: x86_64-apple-darwin
release: 1.54.0-nightly
LLVM version: 12.0.1
更新 2: 我想澄清我对这个问题的关注。我想知道提出的“堆栈重用优化”属于哪个类别。
- 这是无效的优化。在某些情况下,如果我们执行“优化”,编译的代码可能会失败。
- 这是一个有效的优化,但编译器(包括 rustc 前端和 llvm)无法执行它。
- 这是一个有效的优化,但暂时关闭,如this。
- 这是一个有效的优化,但被遗漏了。将来会添加。
【问题讨论】:
-
因为你使用它的地址
-
如链接问题中答案的rest所述,由LLVM选择是否为内存中的不同对象重用地址空间,并观察地址堆栈中的值会影响编译输出。 Rust 编译器本身不会强加一种行为。
-
@trentcl 我将再次反对打印应该放弃优化的想法:获取引用在 rust 中绝对无处不在,大多数方法调用都会这样做。如果这足以deopt那么我们就有问题(如果不是一个大问题)。尽管 Emoun 下面的调查似乎暗示问题可能出在其他地方。
-
@Masklinn 你错了。单独获取引用不会抑制优化,因为对象的地址对代码的行为没有任何可观察到的影响。直接打印或以其他方式观察对象的地址确实会抑制优化,因为优化器必须使用非本地推理来得出允许打印“任何”值的结论。
-
@trentcl 我刚刚创建了另一个示例。 godbolt.org/z/TEY76Wsjj 在此示例中,(1)
.push_str()强制 String 实例占用堆栈上的空间 (2) 不会改变任何可观察的行为,因为没有任何东西是可观察的 (3) 在s结束其生命周期后不会重用空间
标签: rust llvm compiler-optimization