我在尝试此代码时遇到错误,它实现了一个简单的链接列表 .
use std::rc::Rc;
use std::cell::RefCell;
struct Node {
a : Option<Rc<RefCell<Node>>>,
value: i32
}
impl Node {
fn new(value: i32) -> Rc<RefCell<Node>> {
let node = Node {
a: None,
value: value
};
Rc::new(RefCell::new(node))
}
}
fn main() {
let first = Node::new(0);
let mut t = first.clone();
for i in 1 .. 10_000
{
if t.borrow().a.is_none() {
t.borrow_mut().a = Some(Node::new(i));
}
if t.borrow().a.is_some() {
t = t.borrow().a.as_ref().unwrap().clone();
}
}
println!("Done!");
}
为什么会这样?这是否意味着Rust不如定位那么安全?
UPD:如果我添加此方法,程序不会崩溃 .
impl Drop for Node {
fn drop(&mut self) {
let mut children = mem::replace(&mut self.a, None);
loop {
children = match children {
Some(mut n) => mem::replace(&mut n.borrow_mut().a, None),
None => break,
}
}
}
}
但我不确定这是否是正确的解决方案 .
1 回答
Rust只能安全地抵御某些类型的故障;特别是内存损坏崩溃,这里记录:http://doc.rust-lang.org/reference.html#behavior-considered-undefined
不幸的是,有时候人们会期望生锈对某些不是内存破坏的故障更加强大 . 具体来说,你应该阅读http://doc.rust-lang.org/reference.html#behavior-considered-undefined .
tldr;在生锈中,许多事情都会引起恐慌 . 紧急情况将导致当前线程停止,执行关闭操作 .
这可能表面看起来类似于内存破坏来自其他语言的崩溃,但重要的是要理解虽然它是一个应用程序失败,但它不是破坏内存的失败 .
例如,您可以通过在不同的线程中运行操作来处理恐慌,例如异常,并在线程发生混乱时(无论出于何种原因)正常处理失败 .
在此特定示例中,您在堆栈上占用了太多内存 .
这个简单的例子也会失败:
(在大多数rustc;取决于特定实现的堆栈大小)
我原本以为使用Box :: new()将分配移动到堆栈会在此示例中修复它...
......但事实并非如此 . 我真的不明白为什么,但希望其他人可以看看这个,并发布一个更权威的答案,关于究竟是什么导致代码中的堆栈耗尽 .