You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

dyn trait指针场景下Debug实现异常:地址打印一致问题求助

dyn trait引用Debug显示地址相同但PartialEq判断不等的原因

我需要比较包含trait引用的结构体,只关注两个引用是否指向同一内存地址。测试中PartialEq能正确判断两个不同实例的引用不等,但Debug输出却显示二者地址相同,这让我很困惑。

可复现Debug问题的代码如下:

#[derive(Debug, PartialEq)]
struct Intersection<'a> {
    intersected: &'a dyn Intersectable,
}

trait Intersectable {}
impl<'a> core::fmt::Debug for dyn Intersectable + 'a {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Intersectable{{{:?}}}", core::ptr::addr_of!(self))
    }
}
impl<'a> PartialEq for dyn Intersectable + 'a {
    fn eq(&self, other: &Self) -> bool {
        std::ptr::eq(self, other)
    }
}

#[derive(Debug, PartialEq)]
struct Sphere {}
impl Intersectable for Sphere {}

#[test]
fn comparison_bug() {
    let sphere = Sphere{};
    let other = Sphere{};
    let i = Intersection{ intersected: &sphere };

    assert_eq!(i.intersected, &sphere as &dyn Intersectable);
    assert_eq!(i.intersected, &other as &dyn Intersectable);
}

测试中第二个断言正确失败,但输出的Debug信息显示左右侧地址相同:

assertion failed: `(left == right)`
  left: `Intersectable{0x7faebfa72188}`,
 right: `Intersectable{0x7faebfa72188}`

问题原因

你在Debug实现里犯了一个关键错误:

  • fmt方法中的self是&dyn Intersectable类型(对dyn trait胖指针的引用),core::ptr::addr_of!(self)取的是这个引用自身在栈上的地址,而不是胖指针指向的实例地址。
  • 测试时,右边的&other as &dyn Intersectable是临时创建的栈变量,编译器优化后可能和左边的引用复用了同一个栈位置,导致打印出的地址相同。但实际上两个胖指针内部指向的实例地址是不同的,所以PartialEq的判断是正确的。

解决方法

修改Debug实现,打印胖指针指向的实例地址(即胖指针中的数据指针部分):

impl<'a> core::fmt::Debug for dyn Intersectable + 'a {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        // 将dyn trait引用转换为原始指针,提取数据地址
        let instance_ptr = self as *const dyn Intersectable as *const ();
        write!(f, "Intersectable{{{:?}}}", instance_ptr)
    }
}

修改后再运行测试,断言失败时会显示不同的实例地址,和PartialEq的判断结果一致。

内容的提问来源于stack exchange,提问作者Nathaniel Waisbrot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 20:22:41