- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在使用 Marshal.AllocHGlobal
c# 方法为 IntPtr 分配内存,然后复制 byte[] 的包含:
byte[] clientIpAddr = System.Text.Encoding.ASCII.GetBytes("127.0.0.1")
IntPtr client_ipAddr_p = IntPtr.Zero;
ipAddress_p = Marshal.AllocHGlobal(clientIpAddr.Length);
Marshal.Copy(clientIpAddr, 0, ipAddress_p, clientIpAddr.Length);
然后我将指针传递给接收我的变量的 C++ 外部库,如下所示:
int open_socket(char *clientIpAddr_p)
{
<open a socket>
}
根据 AllocHGlobal
的定义,它最终可能会保留比预期更多的内存(我可以保证,因为我现在正在遭受它)。问题是我需要我的 IntPtr
具有我请求的大小,因为我需要 IP 是准确的以便之后打开套接字。
有没有更好的方法来分配外部内存以确保 char *
拥有我正确的 IP?
最佳答案
Marshal.AllocHGlobal 分配的内存多于指定的内存量不是问题。您的代码遇到了一个不同且很可能是致命的问题。
open_socket(char *clientIpAddr_p)
需要一个指向 C 风格的指针 null-terminated string (也称为以 NUL 结尾的字符串、以零结尾的字符串或 ASCIIZ)。但是,您的 C# 代码会创建一个缓冲区并用字符串字符/字节填充它,而不用空字符终止它。这很可能会导致 open_socket 函数崩溃或在内存中(从指针给定的地址开始)搜索丢失的空字符时出现其他错误。
一个可能的解决方法相当简单:分配大小为 clientIpAddr.Length + 1
的缓冲区,考虑终止空字符。必须显式设置零终止符(空字节),因为 Marshal.AllocHGlobal 不会用空字节初始化/填充分配的缓冲区。由于我们在这里处理的是 ASCII/ANSI 字符串,因此空字符只是一个值为零的字节。
byte[] clientIpAddr = System.Text.Encoding.ASCII.GetBytes("127.0.0.1")
IntPtr client_ipAddr_p = Marshal.AllocHGlobal(clientIpAddr.Length + 1);
Marshal.Copy(clientIpAddr, 0, ipAddress_p, clientIpAddr.Length);
Marshal.WriteByte(client_ipAddr_p, clientIpAddr.Length, 0);
好吧,忘掉我刚写的代码。 ;-)
为什么?因为有一个更简单的“一站式”解决方案,使您免于手动分配和填充 C 风格空终止字符串的缓冲区的麻烦: Marshal.StringToHGlobalAnsi
方法,该方法会将带有 IP 地址的 .NET 字符串直接转换为相应的 C 样式的以 null 结尾的 ANSI 字符串。
string ipAddress = "127.0.0.1";
IntPtr client_ipAddr_p = Marshal.StringToHGlobalAnsi(ipAddress);
(除非 open_socket 函数要求 clientIpAddr_p 指向的字符串缓冲区在调用后继续存在,否则使用 Marshal.FreeHGlobal< 释放分配的缓冲区
调用 native 函数后的方法,无论缓冲区是否已使用 Marshal.AllocHGlobal 或 Marshal.StringToHGlobalAnsi 分配。)
关于c# - Marshal.AllocHGlobal 正在分配比预期更多的内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56307553/
我正在使用 Marshal.AllocHGlobal c# 方法为 IntPtr 分配内存,然后复制 byte[] 的包含: byte[] clientIpAddr = System.Text.Enc
来自 Marshal.AllocHGlobal 的 MSDN 文档: AllocHGlobal is one of two memory allocation methods in the Marsh
Marshal 中有多种方法可以将 AllocHGlobal 分配的原始缓冲区复制到 C# 数组或从 C# 数组复制。但我的问题是,我有两个缓冲区都是由 AllocHGlobal 分配的,我想简单地将
我有一个第 3 方 C 库,其导出方法之一如下: #define MAX_INDEX 8 int GetStuff(IN char* index[MAX_INDEX], OUT char* buf,
我正在通过 Marshal.AllocHGlobal 在我的应用程序中分配一些非托管内存。然后,我将一组字节复制到该位置,并将生成的内存段转换为 struct,然后通过 Marshal.FreeHGl
我正在连接的遗留数据库使用数据缓冲区将行传递给应用程序。为了在 C# 中处理这个问题,我编写了一个类,它提供了在缓冲区中读取和写入不同类型的方法。每个数据文件使用一个数据缓冲区,但必须为某些操作调整缓
我读过,在 Windows 上,malloc 不同于 CoTaskMemAlloc,后者又不同于 AllocHGlobal。对于 C# 使用者,这可能意味着如果我有一个返回 malloc 指针的 C
我用 C# 编写了一个模块,导出了一些要在 C 中使用的函数。我需要为一些要在 C C# 之间传递的结构分配一些内存。 我在 C 中分配的内容使用 malloc,而在 C# 中我使用 Marshal
只是想了解这是否有意义,以及它的意义在哪里。 Marshal.AllocHGlobal(int cb) 在非托管内存中分配指定数量的字节。 但为什么 Marshal.AllocHGlobal(0) 实
我写了一个辅助方法, internal static IntPtr StructToPtr(object obj) { var ptr = Marshal.AllocHGlobal(Marsh
我不清楚 native 互操作的机制。 假设我执行以下操作: IntPtr nativeArray = Marshal.AllocHGlobal(stride * height); someNativ
首先我要说的是,我在整个论坛和网络上的许多链接中查看并找到了有关使用 fixed{}、Marshal.AllocHGlobal() 和 GCHandle.Alloc() 的描述。但是,我还没有找到关于
我有以下结构: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct WAVEHDR { in
我有一个 .Net 类,它使用 struct 为 Marshal.AllocHGlobal 分配非托管内存,然后使用 Marshal.FreeHGlobal 处理它。 我知道类 Microsoft.W
我是一名优秀的程序员,十分优秀!