分配“非托管” C# 中的内存

发布于 2024-08-29 05:40:59 字数 113 浏览 9 评论 0原文

我正在用 C# 编写一个使用 C++ 库的程序,由于某种原因,我需要分配一个非托管缓冲区以将其传递给库。有没有办法在 c# 中做到这一点? 基本上我只需要在 C# 中进行 malloc...

谢谢

I'm writting a program in c# that uses a C++ library, and for some reason I need to allocate an unmanaged buffer to pass it to the lib. Is there a way to do this in c# ?
Basically I would just need to do a malloc in C#...

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一口甜 2024-09-05 05:40:59

尝试这样的操作:

using System;
using System.Runtime.InteropServices;

class Example
{
    static void Main()
    {
        IntPtr pointer = Marshal.AllocHGlobal(1024);
    }
}

这使用 Marshal.AllocHGlobal< /a> 方法:

使用指定的字节数从进程的非托管内存中分配内存。

Try something like this:

using System;
using System.Runtime.InteropServices;

class Example
{
    static void Main()
    {
        IntPtr pointer = Marshal.AllocHGlobal(1024);
    }
}

This uses the Marshal.AllocHGlobal method:

Allocates memory from the unmanaged memory of the process by using the specified number of bytes.

半衬遮猫 2024-09-05 05:40:59

您还可以为此使用字节数组。

您可以通过使用不安全的例程和固定语句来完成此操作:

static unsafe void PerformOperation()
{
    byte[] buf = new byte[1024];
    fixed (void* ptr = &buf[0])
    {
        SomeUnmanagedFunction(new IntPtr(ptr));
    }
}

问题(这是一个重要的问题)是,在返回并且代码退出固定块后,不允许 SomeUnmanagedFunction 接触该指针。因此,如果你做这样的事情:

static void PerformFabulousTrick()
{
    byte[] buf = new byte[1024];
    fixed (void *ptr = &buf[0])
    {
        SetBuffer(ptr, buf.Length);
    }
    FillBuffer(); // puts data in buf - NOT - may crash hard
}

你只会带来麻烦。在这种情况下,您可能想要使用 GCHandle,它可以将托管对象固定在堆中。这也可能很麻烦,因为您需要及时取消固定它,否则您可能会面临堆碎片的风险。

一般来说,我建议确保您正确地 P/Invoking 到函数中,以便编组器可以为您完成这项工作。与 GlobalAlloc 相比,我更喜欢fixed,因为它的范围很明确。我无法决定 GlobalAlloc 和 GCHandle 中我最不喜欢哪一个。两者都要求您做更多的工作,因为 GC 或语言不会为您做这些工作。

You can also use a byte array for this.

You do this by using an unsafe routine and the fixed statement:

static unsafe void PerformOperation()
{
    byte[] buf = new byte[1024];
    fixed (void* ptr = &buf[0])
    {
        SomeUnmanagedFunction(new IntPtr(ptr));
    }
}

The issue - and this is an important one - is that SomeUnmanagedFunction is not allowed to touch that pointer after it has returned and code has exited the fixed block. So if you do something like this:

static void PerformFabulousTrick()
{
    byte[] buf = new byte[1024];
    fixed (void *ptr = &buf[0])
    {
        SetBuffer(ptr, buf.Length);
    }
    FillBuffer(); // puts data in buf - NOT - may crash hard
}

you are asking for nothing but trouble. In this case you probably want to use a GCHandle, which can pin a managed object in the heap. This can also be troublesome in that you NEED to unpin it in a timely manner or you risk fragmenting your heap.

In general, I would recommend making sure that you're P/Invoking correctly into the function so that the maybe marshaller can do this work for you. I like fixed better than GlobalAlloc since its scope is clear. I can't decide which I like least of GlobalAlloc and GCHandle. Both require you to do more work since the GC or language won't do it for you.

牵强ㄟ 2024-09-05 05:40:59

这就是我们需要使用特定字节数来分配和释放非托管内存的方式。

// Demonstrate how to call GlobalAlloc and 
// GlobalFree using the Marshal class.
IntPtr hglobal = Marshal.AllocHGlobal(100);
Marshal.FreeHGlobal(hglobal)

This is how we need to assign and free unmanaged memory by using specific number of bytes.

// Demonstrate how to call GlobalAlloc and 
// GlobalFree using the Marshal class.
IntPtr hglobal = Marshal.AllocHGlobal(100);
Marshal.FreeHGlobal(hglobal)
爱的故事 2024-09-05 05:40:59

几年后,与此同时:
在 .net6、7 中,MS 为我们提供了“NativeMemory”类,其中包含“AlignedAlloc”等方法,这对于矢量化应用程序可能很有用:MS 在本示例中写道

public static void* AlignedAlloc (UIntPtr byteCount, UIntPtr alignment);

“此方法是 Clined_alloc API 或依赖于平台的对齐分配 API(例如 Win32 上的 _aligned_malloc)的精简包装。”

当然,在这种情况下就没有垃圾收集。必须使用“AlignedFree”自行释放内存以避免内存泄漏。

Years later, in the meantime:
In .net6, 7, MS gifted us with the class "NativeMemory" with methods like "AlignedAlloc", which might be useful for vectorized applications: MS writes for this example:

public static void* AlignedAlloc (UIntPtr byteCount, UIntPtr alignment);

"This method is a thin wrapper over the C aligned_alloc API or a platform dependent aligned allocation API such as _aligned_malloc on Win32."

Of course, no garbage collection in that case. One has to release the memory oneself to avoid memory leaks, by using "AlignedFree".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文