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

.NET中为何新分配对象内存地址重复?如何解决?

问题原因分析

你遇到的问题核心在于你打印的是栈上局部引用变量的地址,而非托管堆上Node实例的真实地址:

  • 在C#中,Node是引用类型,当你执行new Node(value)时,对象实例会被分配在托管堆上;而方法内的node变量是一个存储在栈上的引用(它的值是堆上实例的地址)。
  • 每次调用Add方法时,方法的栈帧会被重复利用,局部变量node在栈上的位置是固定的,所以你用&node获取的是这个栈上变量的地址,自然每次都完全相同。
  • 你真正需要观察的是堆上每个Node实例的地址,而不是栈上引用变量的地址。
解决办法

要获取托管堆上对象实例的真实地址,可以通过两种常用方式实现:

方式一:使用Unsafe类(更简洁)

通过System.Runtime.CompilerServices.Unsafe类的AsPointer方法,直接获取引用指向的堆实例地址:

首先确保你的项目引用了System.Runtime.CompilerServices.Unsafe包(.NET Core/.NET 5+通常已内置),然后修改Add方法的unsafe代码块:

using System.Runtime.CompilerServices;

// ...

public void Add(int value)
{
    Node node = new(value);
    _nodes.Add(node);
    unsafe
    {
        // 获取堆上Node实例的地址
        ulong instanceAddress = (ulong)Unsafe.AsPointer(ref node);
        Console.WriteLine("Address of new node instance: {0}", instanceAddress);
    }
}

方式二:使用GCHandle(更安全,适合需要固定对象的场景)

通过System.Runtime.InteropServices.GCHandle固定对象(防止GC移动它),然后获取其地址:

using System.Runtime.InteropServices;

// ...

public void Add(int value)
{
    Node node = new(value);
    _nodes.Add(node);
    unsafe
    {
        GCHandle handle = GCHandle.Alloc(node, GCHandleType.Pinned);
        try
        {
            ulong instanceAddress = (ulong)handle.AddrOfPinnedObject();
            Console.WriteLine("Address of new node instance: {0}", instanceAddress);
        }
        finally
        {
            handle.Free(); // 必须释放句柄,避免内存泄漏
        }
    }
}
验证效果

修改后运行代码,你会看到控制台输出的地址不再重复,每个Node实例的堆地址都是唯一的,完全符合你开发XOR链表的需求。

内容的提问来源于stack exchange,提问作者Jossean Yamil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 18:45:48