首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >持久记忆混淆

持久记忆混淆
EN

Stack Overflow用户
提问于 2015-11-14 21:24:09
回答 2查看 104关注 0票数 2

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

代码语言:javascript
复制
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);
    }
}

我知道它在最后失去了自由,但这只是导致了混乱的内存管理.我正在寻找是否有人可以帮助我,并解释为什么sz不停留为值6时,第二个函数被调用…

ran时的输出是:

代码语言:javascript
复制
Changed sz to be 6
sz is = 0
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-11-14 21:35:21

这都是因为valuestruct

GCHandle.Alloc接受一个object参数,所以如果您传递一个struct,它必须被装箱。

稍后当您使用

代码语言:javascript
复制
value val = (value)gch.Target;

它必须取消装箱,因此它的副本存储在val中。以后所做的任何修改都是在副本上进行的,而不是在装箱的struct上进行的。

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

票数 2
EN

Stack Overflow用户

发布于 2015-11-14 21:40:24

因为value是一个sturct,而结构不是引用类型。当您有一个struct和var b = instanceOfStruct的实例时,b是一个新的结构,而不是对instanceOfStruct的引用。b中的循环值不反映给instanceOfStruct

在您的代码中:

代码语言:javascript
复制
value val = (value)gch.Target;

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

代码语言:javascript
复制
dynamic val = gch.Target;
val.sz = 6;
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33713541

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档