Arc 递归指针 销毁栈溢出 有没有解决方法

Demo#

use std::sync::{Arc, Weak};
trait TestTrait {}
struct Test(Option<Arc<dyn TestTrait>>);

impl TestTrait for Test {}

#[test]
fn arc_test(){
    let mut ptr:Arc<dyn TestTrait> = Arc::new(Test(None));
    for _ in 1..1000000{
        ptr = Arc::new(Test(Some(Arc::clone(&ptr))))
    }
}

来源#

代码已被折叠,点此展开
謎麟
讨论数量: 2
Oraoto
impl Drop for Test {
    fn drop(&mut self) {
        let mut test = self;
        let mut arcs = vec![];
        loop {
            // base case
            if test.0.is_none() {
                return;
            }

            // test = Test(None), option = Arc<dyn TestTrait>
            let mut option = None;
            std::mem::swap(&mut test.0, &mut option);

            // get a raw pointer, to go to next element
            let arc = option.unwrap();
            let raw = Arc::into_raw(arc);
            test = unsafe {&mut *(raw as *mut Test)};

            // convert back to Arc, to avoid memory leak
            let arc = unsafe {Arc::from_raw(raw)};
            arcs.push(arc);
        }
    }
}

基本思路是把递归转成迭代,本来有一条 Some -> Arc -> Some -> Arc -> Some .... 这样的链,递归 drop 会 stackoverflow,我一个一个地把 Some 换成 None,断掉这个链,变成 [Arc->None, Arc->None ....] 这样的一个 vec,由 vec 迭代 drop 掉每个 Arc。

不过用了 unsafe,不知有没更好的方法。

3年前 评论
MaxKing (楼主) 3年前