panic!
宏对当前线程的影响
- 终止当前线程执行:当在Rust程序中调用
panic!
宏时,它会立即终止当前线程的正常执行流程。
- 展开(Unwinding)栈:默认情况下,
panic!
会导致栈展开(unwind)。这意味着它会从发生panic
的地方开始,反向遍历调用栈,释放栈上的局部变量所占用的资源,调用这些局部变量的析构函数(如果有)。例如:
fn main() {
let s = String::from("hello");
panic!("Something went wrong");
// 这里的代码不会被执行,但是`s`的析构函数会在栈展开时被调用
}
- 程序终止:如果栈展开完成后,
panic
仍然没有被处理(例如没有捕获panic
),整个程序将会终止,除非这是一个多线程程序中除主线程外的其他线程发生panic
,这种情况下其他线程可能继续运行。
常见主动使用panic!
宏的场景
- 不可恢复的错误:当程序遇到一种无法通过常规手段恢复的错误时,适合使用
panic!
。例如,程序需要读取特定格式的配置文件,但文件格式严重错误,无法进行修复或继续处理。
fn parse_config_file() {
let config = std::fs::read_to_string("config.txt").expect("Failed to read config file");
if config.len() < 10 {
panic!("Config file is too short, expected at least 10 characters");
}
// 这里假设后续处理依赖于配置文件至少有10个字符
}
- 违反内部不变量:如果程序内部的某个不变量被违反,意味着程序的逻辑出现了严重问题,此时可以使用
panic!
。比如,在一个自定义数据结构中,有一个不变量是链表不能有循环,当检测到循环时:
struct Node {
value: i32,
next: Option<Box<Node>>,
}
fn check_no_cycle(node: &Node) {
let mut visited = Vec::new();
let mut current = Some(node);
while let Some(n) = current {
if visited.contains(&n) {
panic!("Detected a cycle in the linked list");
}
visited.push(n);
current = n.next.as_ref().map(|b| &**b);
}
}
- 未实现的功能:在开发过程中,对于一些暂时未实现但计划实现的功能,可以使用
panic!
来提醒开发者该功能尚未完成。例如:
fn future_feature() {
panic!("This feature is not implemented yet");
}