提问人:zilon co 提问时间:11/16/2023 最后编辑:Denis Michealzilon co 更新时间:11/16/2023 访问量:78
解码消息时内存不足异常
Out of memory exception while decoding message
问:
public static byte[] EncodeMessage(string message)
{
try
{
// Convert the string message to a byte array
byte[] messageBytes = System.Text.Encoding.UTF8.GetBytes(message);
// Write the message length as a 4-byte integer followed by the message data
byte[] lengthBytes = BitConverter.GetBytes(messageBytes.Length);
byte[] sendBuffer = new byte[lengthBytes.Length + messageBytes.Length];
Array.Copy(lengthBytes, sendBuffer, lengthBytes.Length);
Array.Copy(messageBytes, 0, sendBuffer, lengthBytes.Length, messageBytes.Length);
return sendBuffer;
}
catch (EncoderFallbackException ex)
{
// Handle encoding error (e.g., log, throw, or return a default value)
Console.WriteLine($"Error encoding message: {ex.Message}");
return null; // or throw an exception or return a default value
}
catch (Exception ex)
{
return null;
}
}
public static string DecodeMessage(byte[] data)
{
try
{
// Read the 4-byte header to get the length of the message
byte[] lengthBytes = new byte[4];
Debug.WriteLine(data.Length.ToString());
Array.Copy(data, lengthBytes, lengthBytes.Length);
int messageLength = BitConverter.ToInt32(lengthBytes, 0);
// Read the message data into a byte array
byte[] messageData = new byte[messageLength];
Array.Copy(data, lengthBytes.Length, messageData, 0, messageLength);
// Convert the message data to a string
string message = System.Text.Encoding.UTF8.GetString(messageData);
return message;
}
catch (Exception ex)
{
return null;
}
}
我在这一行的功能中出现了内存不足异常。总的来说,当更改(如5762781类似的东西)时,它会在其他方面(如 4561 等)出现内存不足异常,然后它工作正常,没有问题)。我在这里做错了什么?DecodeMessage
int messageLength = BitConverter.ToInt32(lengthBytes, 0)
messageLength
我也尝试了字节序,但没有用。
答:
这是我在这里看到的:
函数中的 your 可能是由于分配的内存不足来读取消息数据。
OutOfMemoryException
DecodeMessage
当消息长度较大时,该方法会尝试分配一个更大的字节数组,该数组可能会超过可用内存。
messageData
为了有效地处理较大的消息并防止与内存相关的问题,您可以选择流式传输数据,而不是一次读取整个消息。这样,您就可以在较小或可管理的数据块中处理消息。
我建议你使用 try catch 来捕获错误并使用MemoryStream
public static string DecodeMessage(byte[] data)
{
try
{
using (MemoryStream memoryStream = new MemoryStream(data))
{
// Read the 4-byte header to get the length of the message
byte[] lengthBytes = new byte[4];
memoryStream.Read(lengthBytes, 0, lengthBytes.Length);
int messageLength = BitConverter.ToInt32(lengthBytes, 0);
// Read the message data into a byte array
byte[] messageData = new byte[messageLength];
int bytesRead = 0;
int bytesToRead = messageLength;
while (bytesToRead > 0)
{
int chunkSize = memoryStream.Read(messageData, bytesRead, bytesToRead);
if (chunkSize <= 0)
{
throw new EndOfStreamException("Unexpected end of stream");
}
bytesRead += chunkSize;
bytesToRead -= chunkSize;
}
// Convert the message data to a string
string message = System.Text.Encoding.UTF8.GetString(messageData);
return message;
}
}
catch (Exception ex)
{
Console.WriteLine($"Error decoding message: {ex.Message}");
return null;
}
}
评论
我无法发现任何特定错误。但是,如果目标只是将字符串转换为字节,然后再转换回来,那么您自己就会变得复杂。只需使用 StreamWriter/StreamReader:
[Test]
public void EncodeDecodeTest()
{
var targetMs = new MemoryStream();
var message = "hello world";
EncodeMessage(targetMs, message);
var bytes = targetMs.ToArray();
var sourceMs = new MemoryStream(bytes);
var result = DecodeMessage(sourceMs);
Assert.AreEqual(result, message);
}
public void EncodeMessage(Stream target, string message)
{
using var sw = new StreamWriter(target, Encoding.UTF8, 4096, leaveOpen:true);
sw.Write(message);
}
public string DecodeMessage(Stream source)
{
using var sr = new StreamReader(source, Encoding.UTF8, false, 4096, leaveOpen: true);
return sr.ReadToEnd();
}
在读取或写入数据时,通常应尝试使用流,因为这允许您直接处理文件或网络流,而无需缓冲内存中的所有内容。如果你需要一个实际的字节数组,可以很容易地将内存流转换为字节,反之亦然,如示例所示。或者,如果要将整个对象转换为字节,请使用序列化库,如 json。
其他需要检查的事项是消息长度,6Mb 字符串应该不会导致任何问题,但如果您开始接近 2Gb,则有一些限制可能会导致问题。您可能还需要检查是否在 x64 而不是 x86 中运行,以确保您确实有可用内存。使用已知输入编写单元测试也非常有用,因此您可以确认功能是否正常工作,而无需考虑应用程序的其余部分。
评论