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

在Rust #[no_std]环境中如何获取panic消息?

在#[no_std]环境中捕获panic原因及处理编译器生成的panic payload

编译器生成的panic payload类型

对于算术溢出、数组越界这类Rust内置调试检查触发的panic,编译器默认会生成**&'static str类型的payload**,而非String——这是因为#[no_std]环境默认不包含alloc crate,String依赖堆分配无法直接使用。你之前尝试用downcast_ref::<String>()自然拿不到数据,换成downcast_ref::<&str>()就能捕获这类内置panic的原因。

实现能捕获原因的自定义panic handler

下面是适配#[no_std]的panic handler示例,同时获取文件、行号和panic原因:

#![no_std]
#![no_main]
#![panic_handler = "custom_panic"]

use core::panic::PanicInfo;

#[panic_handler]
fn custom_panic(info: &PanicInfo) -> ! {
    // 获取panic发生的位置信息
    let location = info.location().unwrap();
    let file = location.file();
    let line = location.line();

    // 获取panic原因
    let msg = match info.payload().downcast_ref::<&str>() {
        Some(s) => *s,
        None => "Unknown panic reason",
    };

    // 替换成你嵌入式环境的输出逻辑(比如串口打印)
    // 示例:uart_println!("Panic at {}:{} - {}", file, line, msg);

    loop {} // 或调用硬件中止逻辑
}

// 示例:触发算术溢出panic(debug模式默认启用溢出检查)
#[no_mangle]
fn main() {
    let x: u8 = 255;
    let _y = x + 1; // 触发算术溢出panic
}

自定义可打印的panic payload(可选)

如果需要自定义panic信息格式,可以定义轻量结构体(无需堆分配),实现core::fmt::Display或core::fmt::Debug,再在panic!宏中传入:

use core::fmt;

#[derive(Debug)]
struct CustomPanicPayload {
    module: &'static str,
    code: u32,
}

impl fmt::Display for CustomPanicPayload {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Module {} error code: {}", self.module, self.code)
    }
}

// 在代码中触发自定义panic
panic!(CustomPanicPayload { module: "UART", code: 0x01 });

// 在panic handler中捕获
let msg_buffer = [0u8; 64]; // 静态缓冲区,无需堆分配
let mut writer = core::fmt::Write::new(&mut msg_buffer[..]);

match info.payload().downcast_ref::<CustomPanicPayload>() {
    Some(payload) => let _ = write!(writer, "{}", payload),
    None => {
        let default_msg = info.payload().downcast_ref::<&str>().unwrap_or("Unknown panic");
        let _ = write!(writer, "{}", default_msg);
    }
};

// 输出msg_buffer中的内容到硬件

如果你的#[no_std]环境未启用alloc,全程用静态缓冲区配合core::fmt即可避免堆分配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:17:21