繁体   English   中英

Marshal.AllocHGlobal正在分配比预期更多的内存

[英]Marshal.AllocHGlobal is allocating more memory than expected

我正在使用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终止的字符串 (也称为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样式以null终止的字符串的麻烦: Marshal.StringToHGlobalAnsi方法,它将转换您的.NET将IP地址的字符串直接转换为对应的C样式的以N结尾的ANSI字符串。

string ipAddress = "127.0.0.1";
IntPtr client_ipAddr_p = Marshal.StringToHGlobalAnsi(ipAddress);

(除非open_socket函数要求由clientIpAddr_p指向的字符串缓冲区在调用后继续存在,请在调用本机函数后使用Marshal.FreeHGlobal方法释放已分配的缓冲区,而不管该缓冲区是使用Marshal.AllocHGlobal还是Marshal分配的.StringToHGlobalAnsi 。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM