gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-10-31 00:51:00 27 4
gpt4 key购买 nike

我正在使用 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.AllocHGlobalMarshal.StringToHGlobalAnsi 分配。)

关于c# - Marshal.AllocHGlobal 正在分配比预期更多的内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56307553/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com