代码之家  ›  专栏  ›  技术社区  ›  userx

C中的结构修改会影响非托管内存吗?

  •  9
  • userx  · 技术社区  · 14 年前

    我相信会发生的是: 当从我的非托管DLL中获取一个结构时,这与调用获取一个IntPtr,然后使用它和Marshal类将结构复制到托管内存中是一样的(在托管内存中对结构所做的更改不会冒泡)。

    下面是我的代码:

    [DllImport("mydll.dll", BestFitMapping=false, CharSet=CharSet.Ansi)]
    private static extern int GetStruct(ref MyStruct s);
    
    [StructLayout(LayoutKind.Sequential, Pack=0)]
    struct MyStruct
    {
         public int    Field1;
         public IntPtr Field2;
    }
    
    public void DoSomething()
    {
          MyStruct s = new MyStruct();
          GetStruct(ref s);
    
          s.Field1 = 100; //does unmanaged memory now have 100 in Field1 as well?
          s.Field2 = IntPtr.Zero; //does unmanaged memory now have a NULL pointer in field Field2 as well?
    }
    
    2 回复  |  直到 14 年前
        1
  •  0
  •   Les    14 年前

    结构构造函数是用新操作符调用的,但这并不意味着正在分配内存。结构构造函数不是动态地分配对象并返回对它的引用,而是简单地返回结构值本身(通常在堆栈上的临时位置),然后根据需要复制该值。

    因为“struct”后台存储没有什么特别之处,所以人们不会期望在成员分配之后会有不知名的封送操作。

        2
  •  11
  •   E-rich Richard Schneider    10 年前

    不,P/Invoke封送处理程序将非托管结构成员值复制到该结构的托管版本中。一般来说,结构的托管版本与非托管版本在任何方面都不兼容。内存布局不可发现,这是CLR用来 重新排序

    对于给定的函数签名,修改结构是不可能的,因为您允许填充传递给它的内存。函数本身已经复制了结构。但是,由于Field2值是原始指针,因此可以对其进行分组。如果它指向一个结构,那么用 Marshal.PtrToStructure() . 修改它的托管副本,并使用将其复制回非托管内存 Marshal.StructureToPtr() . 或者直接用封送员.ReadXxx()和WriteXxx()。