我正在跟踪从这个book开始的链表实现. ListNode struct 是这样的-

type Link<T> = Option<Rc<RefCell<Node<T>>>>;

#[derive(Debug)]
pub struct List<T> {
    head: Link<T>,
    tail: Link<T>,
}

#[derive(Debug)]
struct Node<T> {
    elem: T,
    next: Link<T>,
    prev: Link<T>,
}

我有一个类似下面的push_front%的方法-

    pub fn push_front(&mut self, elem: T) {
        let new_node = Node::new(elem);
        let new_node = Rc::new(RefCell::new(new_node));
        let mut old_head = self.head.take();
        old_head.as_mut().map(|node| {
            node.borrow_mut().prev = Some(Rc::clone(&new_node));
        });
        new_node.borrow_mut().next = old_head.clone();
        self.head = Some(new_node);
        if self.tail.is_none() {
            self.tail = self.head.clone();
        }
    }

代码编译得很好.但是,每当我在测试中放置调试印记List时,我都会收到一条测试失败的消息thread 'tests::test_list_1' has overflowed its stack.

    #[test]
    fn test_list_1() {
        let mut list = List::new();
        list.push_front(1);
        list.push_front(2);
        list.push_front(3);
        println!("{:?}", list);
        // assert!(false);
    }

如果我注释掉println!行,则测试通过.因此,基本上list的调试打印导致了这里的堆栈溢出.我不能确切地理解为什么.

Playground Link个完整的代码.

我已经对代码进行了试验,以找出具体是下面一行代码导致的问题.

println!("{:?}", list);

所以我猜想,因为list有一个std::rc::Rc类型,而println!宏引用了这个值,它以某种方式在某个地方创造了一个循环.不过,我不能明确指出问题所在.

推荐答案

派生的impl Debug for Node同时打印prevnext,但prev将try 打印其下一个 node (当前 node ),next将try 打印其prev(同上),因此这是一个无限递归.

您需要手动执行Debug个:

impl<T: Debug> std::fmt::Debug for Node<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("Node")
            .field("elem", &self.elem)
            .field("next", &self.next)
            .finish()
    }
}

如果您不想打印tail,也可以手动为List加上Debug.

Rust相关问答推荐

如何在Rust中为具有多个数据持有者的enum变体编写文档 comments ?

为什么要在WASM库中查看Rust函数需要`#[no_mangle]`?

如何在原始字符串中转义";#和#";

有没有更好的方法从HashMap的条目初始化 struct ?

这种获取-释放关系是如何运作的?

在执行其他工作的同时,从共享裁判后面的VEC中删除重复项

为什么reqwest以文本形式下载二进制文件?

为昂贵的for循环制作筛子

RUST应用程序正在退出,错误代码为:(退出代码:0xc0000005,STATUS_ACCESS_VIOLATION)

用于判断整数块是否连续的SIMD算法.

AXUM一路由多个不包括URL的参数类型

Rust将String上的迭代器转换为&;[&;str]

为什么RefCell没有与常规引用相同的作用域?

我们可以在 Rust 切片中使用步骤吗?

缺失serde的字段无法设置为默认值

如何在 Rust 中编写涉及异步的重试函数

Rust,我如何正确释放堆分配的内存?

有没有办法在 Rust 中对 BigInt 进行正确的位移?

为什么这里需要类型注解?

在 Rust 中组合特征的不同方法是否等效?