gpt4 book ai didi

c# - 固定缓冲区与使用 `MarshalAs` attr 和 `UnmanagedType.ByValArray` 之间有什么区别?

转载 作者:太空狗 更新时间:2023-10-30 01:18:58 27 4
gpt4 key购买 nike

嗯,有一些明显的区别:
固定缓冲区:

  • 它们必须在 unsafe block 中声明(暗示整个项目必须使用 -unsafe 开关编译)。
  • 使用固定缓冲区,包含的对象必须是固定的,

使用 MarshalAs 属性:

  • 虽然大小是给编码器的,但不能保证实际数组有足够的元素数,也不保证它不为空。
  • 该数组可以像任何其他数组一样简单直观地使用。

但我找不到答案的是,为什么首先需要固定缓冲区?
什么时候必须使用它们?
假设可以验证常规托管数组的大小,为什么要使用它?

我能想到性能限制,这可能会让人们选择固定缓冲区而不是常规数组...
这就是全部?

提前致谢。

最佳答案

是的,效率当然是主要原因。当您应用 UnmanagedType.ByValArray 时,结构必须始终 被编码。换句话说,由于结构的非托管布局不同,CLR 被迫创建结构的新副本并使用托管结构中的值对其进行初始化。当您使用固定缓冲区时可以避免这种情况,前提是该结构的其他成员也可以 blittable。在这种情况下,CLR 可以简单地传递一个指向该结构的指针。当然要快得多。

在一些互操作场景中,您必须使用固定大小的缓冲区。通常,当数组成员未对齐时,就会违反 .NET 内存模型的原子性保证。或者您声明一个联合(字段相互重叠)并且 CLR 对象反对将引用类型的字段与值类型的字段重叠。这与垃圾收集器不兼容,它无法可靠地检测到对象指针。在这种情况下,您将在运行时收到 TypeLoadException。

这两种情况基本上都无法验证。如果 native 代码写回结构总是不安全的,当它写到数组末尾时会发生内存损坏。极难诊断。在使用固定大小的缓冲区时显式使用 unsafe 关键字的需要仅适用于在 C# 代码中访问固定大小的缓冲区时缺少索引检查。

关于c# - 固定缓冲区与使用 `MarshalAs` attr 和 `UnmanagedType.ByValArray` 之间有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25011547/

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