gpt4 book ai didi

c# - 了解 C# 中的 GCHandle.Alloc 固定

转载 作者:行者123 更新时间:2023-12-03 21:26:29 27 4
gpt4 key购买 nike

我无意中发现了一些对我来说没有意义的东西。我的问题在代码注释和下面:

[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
[StructLayout(LayoutKind.Sequential, Size = 4096)]
public unsafe struct BufItems
{
public fixed byte Buffer[4096];
}

public class Wrapper
{
public BufItems Items;
public int Id;
}

private unsafe void button10_Click(object sender, EventArgs e)
{
Wrapper wrap = new Wrapper();
wrap.Id = 123;

fixed(BufItems* ptr = &wrap.Items)
{
ptr->Buffer[0] = 99; // works fine
}

// fixed (Wrapper w = wrap) { /* not possible */ };
// fixed (Wrapper* w = &wrap) { /* not possible */ };

// how come I can pin the object this way?
GCHandle h = GCHandle.Alloc(wrap, GCHandleType.Pinned);

// what exactly is p pointing to? Wrapper cannot have a pointer.
IntPtr p = h.AddrOfPinnedObject();
}

我的另一个问题是:我假设字段 BufItems Items被创建为一个对象(因此是可固定的),而不是 wrap 的一部分类对象实例化,对吧?否则固定将无济于事,因为 wrap可以由 GC 移动。但是,它是一个结构体,我认为在这种情况下结构体是“嵌入的”。这里究竟发生了什么?

最佳答案

让我们逐行解决您的问题:

fixed (Wrapper w = wrap)   { /* not possible */ };
fixed只允许声明一个指针变量。但是请注意,固定( fixed 语句所做的)在引用类型上是可能的,但不是那么有用,因此在 C# 中没有任何东西可以使用它。
fixed (Wrapper* w = &wrap) { /* not possible */ };

包装器是一种引用类型。允许您获得指向包含对它的引用的变量的指针,反过来又会允许您访问对象的实际地址,并严重地弄乱它。您可以将指针转换为 object*然后将任何对象存储在变量中,破坏类型安全。
// how come I can pin the object this way?
GCHandle h = GCHandle.Alloc(wrap, GCHandleType.Pinned);

正如我已经说过的,实例固定在 .NET 中是可能的,但在 C# 中在语法上是不可能的。您可以使用此方法固定任何 blittable 类型(无引用字段)。固定对象保证它在堆上的位置不会改变。
// what exactly is p pointing to? Wrapper cannot have a pointer.
IntPtr p = h.AddrOfPinnedObject();

也许最好用这段代码来说明它:
int[] arr = new int[10];
fixed(int* p = arr) { ... }
fixed(int* p = &arr[0]) { ... }

这两行被编译为完全相同的 CIL(为了性能),但第一行也可以通过使用 GCHandle 的方式实现。 AddrOfPinnedObject 返回指向对象中第一个字段的指针,与 fixed(BufItems* ptr = &wrap.Items) 相同.

BufItems 是值类型,因此 Items 字段不包含引用,而是实际的固定数组,以及它后面的 int。

关于c# - 了解 C# 中的 GCHandle.Alloc 固定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45620700/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com