【问题标题】:Persistent memory confusion持久的记忆混乱
【发布时间】:2016-02-16 06:17:47
【问题描述】:

我试图了解 C# 中的持久内存,但不知道为什么这段代码没有保留对其中一个函数所做的更改。

using System;
using System.Runtime.InteropServices;

public class Test2
{
    public struct value
    {
        public int sz;
    }

    public static void Main(string[] args)
    {
        one foo1 = new one(one_full);
        two foo2 = new two(two_full);
        make_calls(foo1, foo2);
    }

    public delegate void one(IntPtr ctx);
    public static void one_full(IntPtr ctx)
    {
        /* set sz and see if persists */
        GCHandle gch = GCHandle.FromIntPtr(ctx);
        value val = (value)gch.Target;

        val.sz = 6;
        Console.WriteLine("Changed sz to be 6");
    }

    public delegate void two(IntPtr ctx);
    public static void two_full(IntPtr ctx)
    {
        GCHandle gch = GCHandle.FromIntPtr(ctx);
        value val = (value)gch.Target;

        Console.Write("sz is = ");
        Console.WriteLine(val.sz);
    }

    public static void make_calls(one f_one, two f_two)
    {
        value test = new value();
        test.sz = 0;

        IntPtr ptr = GCHandle.ToIntPtr(GCHandle.Alloc(test));
        f_one(ptr);
        f_two(ptr);
    }
}

我知道它最后缺少 free 但这只会导致混乱的内存管理....我正在寻找是否有人可以帮助我并解释为什么 sz 在第二个函数被调用...

运行时的输出为:

Changed sz to be 6
sz is = 0

【问题讨论】:

    标签: c# .net memory persistence ref


    【解决方案1】:

    这完全是因为valuestruct

    GCHandle.Alloc 带有一个object 参数,所以如果你传递一个struct,它必须被装箱。

    以后用的时候

    value val = (value)gch.Target;
    

    它必须被拆箱,所以它的副本存储在val。您以后所做的任何修改都是在副本上进行的,而不是在加框的 struct 上。

    它与GCHandle 无关,它是值类型(structs)在 C# 中的工作方式。这就是为什么建议使值类型不可变的原因。

    【讨论】:

    • 酷,谢谢!似乎是正确的,感谢您的解释。
    【解决方案2】:

    因为valuesturct 并且结构不是引用类型。当你有一个结构实例和var b = instanceOfStruct 时,b 是一个新结构,而不是对instanceOfStruct 的引用。 b 中的更改值不会反映到 instanceOfStruct

    在您的代码中:

    value val = (value)gch.Target;
    

    将创建value 结构的新实例,该实例具有与gch.Target 指向它的结构相同的值。更改val 不会更改gch.Target 后面的结构。问题是因为 C# 中的值类型和引用类型之间存在混淆。如果您将value 类型更改为类而不是struct,那么您将获得所需的结果。您也可以使用dynamic 来修改作为句柄目标的结构:

    dynamic val = gch.Target;
    val.sz = 6;
    

    【讨论】:

      猜你喜欢
      • 2013-05-04
      • 2013-05-04
      • 2016-06-27
      • 1970-01-01
      • 2016-10-08
      • 1970-01-01
      • 1970-01-01
      • 2012-06-14
      • 2013-07-17
      相关资源
      最近更新 更多