使用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 bytes

HolotypeTwo.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字节

使用BinaryFormatter进行反序列化会产生OutOfMemoryException

您检查过要反序列化的内容了吗?由于代码中的缺陷,您可能偶尔会在流中获得两个对象。如果'e'字节出现在终止标记之前,CheckByteStringForRO方法可能会跳过终止标记。为了正确捕获这种情况,else条件需要是:

else
{
    tStringIndex = 0;
    if (byteString[i] == TerminationString[tStringIndex])
    {
        tStringIndex++;
    }
}

还有,为什么不创建一个对象集合并序列化它,而不是使用终止标记等等?

相关文章:
  • 没有找到相关文章