使用BinaryFormatter进行反序列化会产生OutOfMemoryException
本文关键字:OutOfMemoryException 反序列化 BinaryFormatter 使用 | 更新日期: 2023-09-27 18:07:06
我正在尝试让客户端应用程序发送一个'MessageObject'到服务器应用程序。
每次我试图在服务器上反序列化MessageObject时,我都会得到一个OutOfMemoryException。
首先,这里是MessageObject类:
[Serializable]
public class MessageObject : ReplicableObject {
public string Command;
public string[] Parameters;
public MessageObject() {
}
public MessageObject(string command, string[] parameters) {
Command = command.ToLower();
Parameters = parameters;
}
}
MessageObject是ReplicableObject的子对象。这里是ReplicableObject:
[Serializable]
public abstract class ReplicableObject {
public string UniqueID {
get {
if (uniqueID == "" || uniqueID == null) {
uniqueID = DateTime.Now.Subtract(new DateTime(1990, 1, 1)).TotalMilliseconds.ToString();
uniqueID = uniqueID.Substring(uniqueID.Length / 2) + Engine.Random(1000000, 9999999).ToString();
}
return uniqueID;
}
private set { uniqueID = value; }
}
private string uniqueID;
[NonSerialized]
public bool RequiresReplication = true;
public ReplicableObject() {
uniqueID = DateTime.Now.Subtract(new DateTime(1990, 1, 1)).TotalMilliseconds.ToString();
uniqueID = uniqueID.Substring(uniqueID.Length / 2) + Engine.Random(1000000, 9999999).ToString();
}
}
当客户端准备好向服务器发送MessageObject时,它使用以下代码:
public static void SerializeRO(Stream stream, ReplicableObject ro) {
Formatter.Serialize(stream, ro);
stream.Write(ASCIIEncoding.ASCII.GetBytes("endhtobject"), 0, 11);
}
TerminationString :
public static byte[] TerminationString = ASCIIEncoding.ASCII.GetBytes("endhtobject");
一旦服务器接收到数据,就调用这个方法(这就是抛出异常的地方):
public static ReplicableObject CheckByteStringForRO(byte[] byteString) {
int tStringIndex = 0;
for (int i = 0; i < byteString.Length; ++i) {
if (byteString[i] == TerminationString[tStringIndex]) {
++tStringIndex;
if (tStringIndex >= TerminationString.Length) {
MemoryStream ms = new MemoryStream();
ms.Write(byteString, 0, i - 10);
ms.Position = 0;
ReplicableObject ro = (ReplicableObject) Formatter.Deserialize(ms);
ms.Close();
return ro;
}
}
else tStringIndex = 0;
}
return null;
}
上面大多数方法只是搜索TerminationString,所以这里是重要的行:
MemoryStream ms = new MemoryStream();
ms.Write(byteString, 0, i - 10);
ms.Position = 0;
ReplicableObject ro = (ReplicableObject) Formatter.Deserialize(ms);
ms.Close();
return ro;
在以'ReplicableObject ro ='开头的那行,抛出OutOfMemoryException。我不明白这是怎么发生的,尤其是考虑到我发送的对象很小。
我应该指出,我是第一次通过网络发送序列化数据,所以我可能在这方面做错了什么。
如果你需要澄清任何事情,请留下评论。:)
谢谢。
编辑:堆栈跟踪异常请求:
mscorlib.dll ! System.Runtime.Serialization.Formatters.Binary.BinaryObjectWithMap.Read (System.Runtime.Serialization.Formatters.Binary._ BinaryParser输入={System.Runtime.Serialization.Formatters.Binary。 _BinaryParser}) +
0 x4f字节mscorlib.dll ! System.Runtime.Serialization.Formatters.Binary._ BinaryParser.ReadObjectWithMap (System.Runtime.Serialization.Formatters.Binary.BinaryHeaderEnumbinaryHeaderEnum) + 0x38 bytes
mscorlib.dll ! System.Runtime.Serialization.Formatters.Binary。 _BinaryParser.Run ()+ 0x304 bytes
mscorlib.dll ! System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize (System.Runtime.Remoting.Messaging.HeaderHandlerHandler = null,System.Runtime.Serialization.Formatters.Binary.__BinaryParserserParser, bool fCheck, bool isCrossAppDomain,System.Runtime.Remoting.Messaging.IMethodCallMessage methodCallMessage= null) + 0xaf bytes
mscorlib.dll ! System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.StreamserializationStream, System.Runtime.Remoting.Messaging.HeaderHandler处理程序,bool fCheck, bool isCrossAppDomain,System.Runtime.Remoting.Messaging.IMethodCallMessagemethodCallMessage) + 0xcf bytes
mscorlib.dll ! System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.StreamserializationStream) + 0x10 bytesHolotypeTwo.dll ! HolotypeTwo.Engine.CheckByteStringForRO (byte []byteString = {byte[8192]})行34 + 0x10字节c#HolotypeServer.exe ! HolotypeServer.UnauthorisedPlayer.StartListening ()第27行+ 0x8字节c#mscorlib.dll ! System.Threading.ThreadHelper.ThreadStart_Context(对象状态)+ 0x63字节
mscorlib.dll ! System.Threading.ExecutionContext.Run (System.Threading.ExecutionContextexecutionContext, System.Threading.ContextCallback, callback, objectstate, bool ignoreSyncCtx) + 0xb0 bytes
mscorlib.dll ! System.Threading.ExecutionContext.Run (System.Threading.ExecutionContextexecutionContext, System.Threading.ContextCallback, callback, object状态)+ 0x2c字节
System.Threading.ThreadHelper.ThreadStart() + 0x44字节
您检查过要反序列化的内容了吗?由于代码中的缺陷,您可能偶尔会在流中获得两个对象。如果'e'字节出现在终止标记之前,CheckByteStringForRO方法可能会跳过终止标记。为了正确捕获这种情况,else条件需要是:
else
{
tStringIndex = 0;
if (byteString[i] == TerminationString[tStringIndex])
{
tStringIndex++;
}
}
还有,为什么不创建一个对象集合并序列化它,而不是使用终止标记等等?