繁体   English   中英

“线 &#39;<main> &#39; 已溢出其堆栈” 构造大树时

[英]“thread '<main>' has overflowed its stack” when constructing a large tree

我实现了一个树结构:

use std::collections::VecDeque;
use std::rc::{Rc, Weak};
use std::cell::RefCell;

struct A {
    children: Option<VecDeque<Rc<RefCell<A>>>>
}

// I got thread '<main>' has overflowed its stack
fn main(){
    let mut tree_stack: VecDeque<Rc<RefCell<A>>> = VecDeque::new();

    // when num is 1000, everything works
    for i in 0..100000 {
        tree_stack.push_back(Rc::new(RefCell::new(A {children: None})));
    }

    println!("{:?}", "reach here means we are not out of mem");
    loop {
        if tree_stack.len() == 1 {break;}

        let mut new_tree_node = Rc::new(RefCell::new(A {children: None}));
        let mut tree_node_children: VecDeque<Rc<RefCell<A>>> = VecDeque::new();

        // combine last two nodes to one new node
        match tree_stack.pop_back() {
            Some(x) => {
                tree_node_children.push_front(x);
            },
            None => {}
        } 
        match tree_stack.pop_back() {
            Some(x) => {
                tree_node_children.push_front(x);
            },
            None => {}
        } 

        new_tree_node.borrow_mut().children = Some(tree_node_children);
        tree_stack.push_back(new_tree_node);
    }
}

围栏链接

但它崩溃了

thread '<main>' has overflowed its stack

我该如何解决?

您遇到的问题是因为您有一个巨大的节点链表。 当该列表被删除时,第一个元素首先尝试释放结构的所有成员。 这意味着第二个元素做同样的事情,依此类推,直到列表的末尾。 这意味着您将拥有一个与列表中元素数量成正比的调用堆栈!

这是一个小复制:

struct A {
    children: Option<Box<A>>
}

fn main() {
    let mut list = A { children: None };

    for _ in 0..1_000_000 {
        list = A { children: Some(Box::new(list)) };
    }
}

以下是您的修复方法:

impl Drop for A {
    fn drop(&mut self) {
        if let Some(mut child) = self.children.take() {
            while let Some(next) = child.children.take() {
                child = next;
            }
        }
    }
}

此代码使用迭代覆盖了默认的递归放置实现。 它将children节点从节点中剥离出来,用一个终端项( None )替换它。 然后它允许节点正常丢弃,但不会有递归调用。

代码有点复杂,因为我们放不下自己,所以我们需要做一点两步舞,忽略第一项,然后把所有孩子都吃掉。

也可以看看:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM