练习题来自:https://practice-zh.course.rs/result-panic/panic.html
1
// 填空
fn drink(beverage: &str) {if beverage == "lemonade" {println!("Success!");// 实现下面的代码__}println!("Exercise Failed if printing out this line!");
}fn main() {drink(__);println!("Exercise Failed if printing out this line!");
}
手动调用panic!
让程序提前挂起即可
fn drink(beverage: &str) {if beverage == "lemonade" {println!("Success!");// 实现下面的代码panic!("bluebonnet27");}println!("Exercise Failed if printing out this line!");
}fn main() {drink("lemonade");println!("Exercise Failed if printing out this line!");
}
Rust的panic!
宏,某种程度上和C++中的abort()
差不多,处理一些不可恢复的错误。我写过一篇文章介绍C++的异常处理(又是一个没填的坑。。。)具体可以看这篇文章的介绍。
2
// 修复所有的 panic,让代码工作
fn main() {assert_eq!("abc".as_bytes(), [96, 97, 98]);let v = vec![1, 2, 3];let ele = v[3];let ele = v.get(3).unwrap();// 大部分时候编译器是可以帮我们提前发现溢出错误,并阻止编译通过。但是也有一些时候,这种溢出问题直到运行期才会出现let v = production_rate_per_hour(2);divide(15, 0);println!("Success!")
}fn divide(x:u8, y:u8) {println!("{}", x / y)
}fn production_rate_per_hour(speed: u8) -> f64 {let cph: u8 = 221;match speed {1..=4 => (speed * cph) as f64,5..=8 => (speed * cph) as f64 * 0.9,9..=10 => (speed * cph) as f64 * 0.77,_ => 0 as f64,}
}pub fn working_items_per_minute(speed: u8) -> u32 {(production_rate_per_hour(speed) / 60 as f64) as u32
}
第一个异常发生在assert_eq!
中,a
的ASCII码是97
,后面以此类推。
assert_eq!("abc".as_bytes(), [97, 98, 99]);
然后是后面的Vec
,很明显越界了。
let v = vec![1, 2, 3];let ele = v[2];let ele = v.get(2).unwrap();
接下来的溢出错误也很明显,Rust的堆栈信息也给得很全面:
thread 'main' panicked at src/main.rs:24:18:
attempt to multiply with overflow
stack backtrace:0: std::panicking::begin_panic_handlerat /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library\std\src\panicking.rs:6521: core::panicking::panic_fmtat /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library\core\src\panicking.rs:722: core::panicking::panic_const::panic_const_mul_overflowat /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library\core\src\panicking.rs:1803: Practice1::production_rate_per_hourat .\src\main.rs:244: Practice1::mainat .\src\main.rs:105: core::ops::function::FnOnce::call_once<void (*)(),tuple$<> >at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081\library\core\src\ops\function.rs:2506: core::hint::black_boxat /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081\library\core\src\hint.rs:338
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
u8的数据,最大也只不过255,这里的乘法基本全部溢出了,随便改个其他不溢出的数就行了。
最后一个是divide,除数为0.
3
## 填空以打印全部的调用栈
## 提示: 你可以在之前的默认 panic 信息中找到相关线索
$ __ cargo run
thread 'main' panicked at 'assertion failed: `(left == right)`left: `[97, 98, 99]`,right: `[96, 97, 98]`', src/main.rs:3:5
stack backtrace:0: rust_begin_unwindat /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/std/src/panicking.rs:498:51: core::panicking::panic_fmtat /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/panicking.rs:116:142: core::panicking::assert_failed_inner3: core::panicking::assert_failedat /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/panicking.rs:154:54: study_cargo::mainat ./src/main.rs:3:55: core::ops::function::FnOnce::call_onceat /rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
如果你用的是Powershell,执行以下命令即可(cmd不能这么写,不过如果你还在用cmd,我强烈建议你换成Powershell)
$env:RUST_BACKTRACE=1 ; cargo run
如果你使用的是 Linux 或 macOS 等 UNIX 系统,一般情况下默认使用的是 bash 命令行,命令如下:
RUST_BACKTRACE=1 cargo run
另外,VS Code自带的Rust插件,执行Run命令的时候,默认是展开全部的调用堆栈的,不需要额外指定环境变量。