You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编译no_std二进制文件时rustc无限挂起问题求助

Troubleshooting Compiler Hang with Static spin::Mutex in Rust OS Development

Hey there, let's break down the compiler hang issue you're facing while working through Writing an Operating System in Rust 2nd Edition, Chapter 3. Even your simplified code gives us clues about the underlying problems—let's tackle them step by step.

1. First, Fix the Obsolete Atomic Initializer

Your simplified code uses ATOMIC_BOOL_INIT, which has been deprecated since Rust 1.34. This isn't the direct cause of the compiler hang, but it's a critical cleanup that avoids warnings and potential edge cases. Replace it with the const-safe constructor:

use core::sync::atomic::{Ordering, AtomicBool};

const ATOMIC_BOOL: AtomicBool = AtomicBool::new(false);

#[no_mangle]
pub extern "C" fn _start() -> ! {
    ATOMIC_BOOL.store(true, Ordering::SeqCst);
    loop {}
}

2. The Root Cause: Static spin::Mutex Initialization

The compiler hang you're seeing with static spin::Mutex almost always stems from one of two issues in no_std environments:

  • Old spin crate versions: Earlier versions of the spin crate didn't support const-safe constructors for Mutex, forcing the compiler to handle runtime initialization during static setup—a process that can trigger infinite loops in the compiler's type checker.
  • Missing const initialization support: Static variables in Rust require compile-time constant values unless you use lazy initialization.

Fixes for Static spin::Mutex:

Option A: Use a spin Version with Const Constructors

Update your Cargo.toml to use spin 0.9 or later (these versions added const-safe Mutex::new):

[dependencies]
spin = "0.9"

Then define your static mutex like this (no compiler hang, since it's initialized at compile time):

static MUTEX: spin::Mutex<u32> = spin::Mutex::new(0);
Option B: Lazy Initialization (For Older spin Versions)

If you need to stick with an older spin version, use once_cell or lazy_static to delay initialization until runtime, avoiding compiler static initialization issues:

use once_cell::sync::OnceCell;
use spin::Mutex;

static MUTEX: OnceCell<Mutex<u32>> = OnceCell::new();

#[no_mangle]
pub extern "C" fn _start() -> ! {
    // Initialize the mutex only once, when first accessed
    let mutex = MUTEX.get_or_init(|| Mutex::new(0));
    let mut value = mutex.lock();
    *value += 1;
    
    loop {}
}

Add once_cell to your Cargo.toml for this to work:

[dependencies]
once_cell = "1.18"
spin = "0.8" # Example older version

3. Complete the Missing panic_fmt Lang Item

Your code cuts off at #[lang = "panic_fmt"]—this incomplete lang item will cause compilation failures even after fixing the mutex issue. You need a minimal implementation for no_std:

#[lang = "panic_fmt"]
pub extern "C" fn panic_fmt(
    _args: core::fmt::Arguments,
    _file: &'static str,
    _line: u32,
) -> ! {
    // Just loop indefinitely on panic (standard for bare-metal OS)
    loop {}
}

Why This Fixes the Compiler Hang

In no_std environments, the Rust compiler can't fall back to standard library runtime initialization logic. When you try to initialize a static Mutex without a const-safe constructor, the compiler struggles to resolve the initialization dependencies, leading to infinite loops in its internal analysis. Using const initialization or lazy runtime initialization breaks this cycle.

内容的提问来源于stack exchange,提问作者user3447239

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:20:00