尽管内存地址相同,Rust Arc 指针比较还是失败

问题描述 投票:0回答:1

在 Rust 中,我试图创建一组可以在某种目标/依赖链中相互关联的对象。我想我可以使用一个特征,并为每个对象分配一个“目标”作为指向链中下一个项目的弱指针。一切都按预期进行,直到我决定进行一些基本的单元测试。我想验证分配的弱指针(升级为 Arc)是否与原始实例相同。但是,在比较两个原始指针时,

assert_eq!()
会失败,即使错误消息显示等式两边的值相同。

这是我所做的简化版本:

use std::{
    fmt::Debug,
    sync::{
        Arc,
        Mutex,
        Weak,
    },
};

pub trait Target: Debug + Send + Sync {
    fn get_target(&self) -> Result<Option<Arc<Mutex<dyn Target>>>, String>;
}

#[derive(Debug)]
pub struct Parent {
    pub id: u32,
    pub target: Option<Weak<Mutex<dyn Target>>>
}
impl Parent {
    pub fn assign_target<T: Target + Debug + Send + Sync + 'static>(&mut self, target: &Arc<Mutex<T>>) {
        self.target = Some(Arc::downgrade(&(target.clone() as Arc<Mutex<dyn Target>>)));
    }
}
impl Target for Parent {
    fn get_target(&self) -> Result<Option<Arc<Mutex<dyn Target>>>, String> {
        if let None = self.target {
            return Ok(None);
        }

        match self.target.as_ref().unwrap().upgrade() {
            Some(target_pointer) => Ok(Some(target_pointer)),
            None => Err("Target object was dropped".to_string())
        }
    }
}

#[derive(Debug)]
pub struct Child {
    pub id: u32
}
impl Target for Child {
    fn get_target(&self) -> Result<Option<Arc<Mutex<dyn Target>>>, String> {
        Ok(None)
    }
}


fn main() {
    // Create object instances
    let child  = Arc::new(Mutex::new(Child { id: 4 }));
    let parent = Arc::new(Mutex::new(Parent { id: 2, target: None }));

    // Assign targets
    parent.try_lock().unwrap().assign_target(&child);

    // Print pointer memory addresses
    println!("Original pointer:                    {:p}", Arc::as_ptr(&child));
    println!("Upgraded pointer assigned to parent: {:p}", Arc::as_ptr(&parent.try_lock()
                                                                             .unwrap()
                                                                             .get_target()
                                                                             .unwrap()
                                                                             .unwrap()));
    println!("Cloned and casted pointer:           {:p}", Arc::as_ptr(&(child.clone() as Arc<Mutex<dyn Target>>)));
    println!("");

    // Compare the target assigned and a direct
    // casted clone of the original object.
    assert_eq!(Arc::as_ptr(&parent.try_lock().unwrap().get_target().unwrap().unwrap()),
               Arc::as_ptr(&(child.clone() as Arc<Mutex<dyn Target>>)));
}

这是我收到的错误消息:

Original pointer:                    0x17308dcab70
Upgraded pointer assigned to parent: 0x17308dcab70
Cloned and casted pointer:           0x17308dcab70

thread 'main' panicked at src\main.rs:68:5:
assertion `left == right` failed
  left: 0x17308dcab70
 right: 0x17308dcab70
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

我做错了什么?如果有任何帮助,我目前正在使用稳定的 Rust v.1.77.2。即使在多台计算机上执行,此错误仍然存在。

unit-testing pointers rust smart-pointers ref
1个回答
0
投票

那是因为您正在比较宽指针,并且比较宽指针还比较元数据,在您的情况下是虚函数表。而且 vtable 可能因多种原因而重复 - 例如,不同的 CGU(代码生成单元)。

您可以使用

Arc::ptr_eq()
std::ptr::addr_eq()
来修复此问题。

© www.soinside.com 2019 - 2024. All rights reserved.