在 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。即使在多台计算机上执行,此错误仍然存在。
那是因为您正在比较宽指针,并且比较宽指针还比较元数据,在您的情况下是虚函数表。而且 vtable 可能因多种原因而重复 - 例如,不同的 CGU(代码生成单元)。
Arc::ptr_eq()
或 std::ptr::addr_eq()
来修复此问题。