首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在托管的.NET代码中分配非托管内存

在托管的.NET代码中分配非托管内存
EN

Stack Overflow用户
提问于 2019-04-18 00:19:16
回答 2查看 0关注 0票数 0

我有一个非托管函数,它接受malloc分配的一块内存,稍后以异步方式释放它。我想将它包装到托管包装器中。下面的代码好吗?

代码语言:javascript
复制
void managed_fx (byte data __gc[], size_t size)
{
    //  Pin the data
    byte __pin *pinned_data = &data [0];

    //  Copy data to the unmanaged buffer.
    void *unmanaged_data = malloc (size);
    memcpy (unmanaged_data, (byte*) pinned_data, size);

    //  Forward the call
    fx (unmanaged_data, size);
}
EN

回答 2

Stack Overflow用户

发布于 2019-04-18 08:30:58

好吧,让我们更简单:

代码语言:javascript
复制
void managed_fx (byte data __gc[])
{
     //  Pin the data
     byte __pin *pinned_data = &data [0];

     //  Copy data to the unmanaged buffer.
     void *unmanaged_data = malloc (data.Length);
     assert (unmanaged_data);
     memcpy (unmanaged_data, (byte*) pinned_data, data.Length);

     //  Forward the call
     fx (unamanged_data, data.Length);
 }

不过,我还有几个问题:

  1. 在这种情况下,钉扎是否必要?在memcpy发生之前,gc可以解除分配吗?
  2. malloc是否分配了非托管内存,即使它在托管代码中使用?
票数 0
EN

Stack Overflow用户

发布于 2019-04-18 09:28:59

你是

  1. 假设数据数组的大小至少相同。这是一个等待发生的错误
  2. 不检查malloc()的结果
  3. 你可能不需要这样做,简单地传递固定字节指针应该没问题(除非被调用的fx()函数以某种方式改变数据,在这种情况下复制可能是一个要求)。基于后来释放的内存,很可能这不是可能的。

考虑到这一点,这是一个固定的版本

代码语言:javascript
复制
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启动移动引用),存在固定指针以使这安全且简单,因为它都需要一个指针并且该指针的生命期阻止运行时将指向变量移动。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100001127

复制
相关文章

相似问题

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