你是
假设数据数组的大小至少一样大。这是一个等待发生的可能错误
不检查 malloc() 的结果
无论如何,您可能不需要这样做,只需传递固定字节指针就可以了(除非调用的 fx() 函数以某种方式更改了数据,在这种情况下可能需要复制)。基于稍后释放的内存,这很可能是不可能的。
考虑到这一点,这里是一个固定版本
void managed_fx (byte data __gc[], size_t size)
{
if (data.Length < size)
throw gcnew System.IndexOutOfRangeException(
"the unmanaged buffer is not big enough");
// Pin the data
byte __pin *pinned_data = &data [0];
// Copy data to the unmanaged buffer.
void *unmanaged_data = malloc (size);
if (unmanaged_data == NULL)
throw gcnew OutOfMemoryException(
"could not allocate memory for the unmanaged buffer");
memcpy (unmanaged_data, (byte*) pinned_data, size);
// Forward the call
fx (unamanged_data, size);
}
要回答进一步的问题:
固定是执行 memcpy 所必需的。它不会阻止 GC 运行时删除内存(从技术上讲,它确实如此,但简单地持有对它的引用也是如此)它会阻止它在内存中移动。由于 memcpy 是一个非托管函数 - 它无法处理它正在操作的指针在内存中移动。malloc 完全是非托管的(尽管运行时库可以自由使用托管堆的保留区域来执行此操作)。
源 C++/CLI 中没有明确区分“代码”是托管还是非托管。在编译时,有些部分是 CIL 中间代码,有些部分是纯原生代码,重要的是变量是否使用的是托管或非托管。托管引用(带有 ^ 的任何内容)只能由本身托管的代码操作/使用。这意味着如果运行时更改了托管对象在内存中的位置,则运行时可以随意更改所使用的底层指针的值。它以对托管函数安全的方式执行此操作(当周围的世界发生变化时,它们会暂停)。由于存在许多有用的函数,但不知道如何处理此类托管引用,因此您最终可能需要获取指向它们的简单指针。由于此操作是不安全的(如果 GC 开始移动引用),存在固定指针以使其安全且易于执行,因为它既需要一个指针,并且该指针的生命周期会阻止运行时移动指向的变量.