【问题标题】:Alternatives to panic!() and expect() for --release?恐慌!()和期望()的替代品--release?
【发布时间】:2020-12-12 06:54:45
【问题描述】:

在开发中,我的代码使用.expect()panic!() 来处理致命错误。

他们的行为正是我在开发过程中所需要的

当我使用--release 编译时,我希望他们的输出会变得更简洁。

即这段代码:

let mut file_a = OpenOptions::new().write(true)
                                   .read(true)
                                   .open(args.file_a).expect("foo bar");

生成:

thread 'main' panicked at 'foo bar: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/bin/vsapply.rs:131:59

当我更喜欢时:

foo bar: No such file or directory

当使用--release编译时。

有没有办法做到这一点?

【问题讨论】:

    标签: rust panic


    【解决方案1】:

    std::panic::set_hook#[cfg(debug_assertions)] 的组合解决了这个问题。

    use std::panic;
    
    fn main() {
        #[cfg(not(debug_assertions))]
        panic::set_hook(Box::new(|panic_info| {
            if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
                println!("panic occurred: {:?}", s);
            } else {
                println!("panic occurred");
            }
        }));
        println!("Hello, world!");
        panic!("nyaan");
    }
    

    执行cargo run时,输出为:

    Hello, world!
    thread 'main' panicked at 'nyaan', src\main.rs:14:5
    

    cargo run --release

    Hello, world!
    panic occurred: "nyaan"
    

    【讨论】:

    • 这不太行。使用--release 会调用挂钩代码,但不会打印额外的信息。例如没有--release 我得到thread 'main' panicked at 'This delta expects file_b to be 43999 bytes long, not 44020 bytes.', src/bin/vsapply.rs:109:9 note: run with 'RUST_BACKTRACE=1' environment variable to display a backtrace 但有--release 我只是得到panic occurred。 (调用代码是panic!("This delta expects file_b to be {:?} bytes long, not {:?} bytes.", len, blen);。)
    • take_hook 保持默认panic! 并在自定义panic! 中调用它似乎很好。 ncaq.net/2019/07/11/18/18/12
    【解决方案2】:

    您可以使用的一个选项是,与其完全恐慌,不如使用eprintln!() 将信息打印到stderr 并以非零错误代码退出。

    use std::process;
    
    fn main() -> {
        // some terrible state
        eprintln!("foo bar: No such file or directory.");
        process::exit(1);
    }
    

    这有几个好处:

    • 打印到 stderr 可确保您的错误消息不会被定向到某个输出文件(例如 foo --option arg1 arg2 &gt; output.txt)。
    • 调用您的程序的程序可以将非零错误代码解释为失败的指示。

    【讨论】:

    • 感谢您的回答。我的代码的每第二行或第三行都是unwrap()expect()。手动检查每个条件会过于冗长并且使代码不可读。您关于 stderr 的观点很重要 - 我将使用 @akihito-kirisaki 和 eprintln!() 的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    • 2021-07-11
    • 2015-12-19
    • 2013-11-21
    • 2021-09-21
    • 2013-12-12
    相关资源
    最近更新 更多