启用优化后,生成线程的程序会发生混乱

Lau*_*nce 9 multithreading rust

当我rustc 1.rs用来编译以下代码时,它会按预期无休止地运行.

use std::thread;

fn main() {
    thread::spawn(|| {
        let a = 2;
        loop {
            a*a;
        }
    }).join();
}
Run Code Online (Sandbox Code Playgroud)

更短的版本:

use std::thread;

fn main() {
    thread::spawn(|| {
        loop {}
    }).join();
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我rustc -O 1.rs用来编译上面的两个程序,它们会崩溃:

thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: Error { repr: Os { code: 0, message: "Success" } }', src/libcore/result.rs:837
stack backtrace:
1:     0x5650bd0acada - std::sys::imp::backtrace::tracing::imp::write::h917062bce4ff48c3
                        at /build/rustc-1.14.0+dfsg1/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:42
2:     0x5650bd0b068f - std::panicking::default_hook::{{closure}}::h0bacac31b5ed1870
                        at /build/rustc-1.14.0+dfsg1/src/libstd/panicking.rs:247
3:     0x5650bd0aee7c - std::panicking::default_hook::h5897799da33ece67
                        at /build/rustc-1.14.0+dfsg1/src/libstd/panicking.rs:263
4:     0x5650bd0af4d7 - std::panicking::rust_panic_with_hook::h109e116a3a861224
                        at /build/rustc-1.14.0+dfsg1/src/libstd/panicking.rs:451
5:     0x5650bd0af364 - std::panicking::begin_panic::hbb38be1379e09df0
                        at /build/rustc-1.14.0+dfsg1/src/libstd/panicking.rs:413
6:     0x5650bd0af289 - std::panicking::begin_panic_fmt::h26713cea9bce3ab0
                        at /build/rustc-1.14.0+dfsg1/src/libstd/panicking.rs:397
7:     0x5650bd0af217 - rust_begin_unwind
                        at /build/rustc-1.14.0+dfsg1/src/libstd/panicking.rs:373
8:     0x5650bd0e2f3d - core::panicking::panic_fmt::hcfbb59eeb7f27f75
                        at /build/rustc-1.14.0+dfsg1/src/libcore/panicking.rs:69
9:     0x5650bd0a6e84 - core::result::unwrap_failed::h15a0fc826f4081f4
10:     0x5650bd0b7ffa - __rust_maybe_catch_panic
                        at /build/rustc-1.14.0+dfsg1/src/libpanic_unwind/lib.rs:97
11:     0x5650bd0a6fc1 - <F as alloc::boxed::FnBox<A>>::call_box::he32a93ebea7bc7ad
12:     0x5650bd0ae6c4 - std::sys::imp::thread::Thread::new::thread_start::ha102a6120fc52763
                        at /build/rustc-1.14.0+dfsg1/src/liballoc/boxed.rs:605
                        at /build/rustc-1.14.0+dfsg1/src/libstd/sys_common/thread.rs:21
                        at /build/rustc-1.14.0+dfsg1/src/libstd/sys/unix/thread.rs:84
13:     0x7fc2d0042423 - start_thread
14:     0x7fc2cfb6e9be - __clone
15:                0x0 - <unknown>
Run Code Online (Sandbox Code Playgroud)

如果我删除闭包中的所有代码,它将退出并且没有错误:

use std::thread;

fn main() {
    thread::spawn(|| {
    }).join();
}
Run Code Online (Sandbox Code Playgroud)

如果我添加println!()循环,它也可以正常工作:

use std::thread;

fn main() {
    thread::spawn(|| {
        loop {
            println!("123")
        }
    }).join();
}
Run Code Online (Sandbox Code Playgroud)

我在Rust 1.14和1.15上测试了这个,同样的问题出现在两者中.

这是因为我使用了什么错误或者它是一个错误?

She*_*ter 6

这是一个已知问题(#28728).简而言之,LLVM优化了没有可观察到的副作用的循环:

实现可以假定任何线程最终将执行以下操作之一:

  • 终止
  • 调用库I/O函数
  • 访问或修改易失性对象,或
  • 执行同步操作或原子操作

在这种情况下,这些都不成立,因此LLVM完全删除了循环.但是,Rust编译器生成的代码假定循环永远不会返回.这种不匹配导致崩溃.

由于具有无副作用的无限循环基本上是无用的,因此该问题不是至关重要的.Rust团队目前正在等待LLVM提供更好的解决方案.

作为一种解决方法,你应该简单地在循环中做一些事情,这可能是你想做的事情^ _ ^