Deserialization using BinaryFormatter throws an OutOfMemoryException

I am trying to get a client application to send MessageObject to a server application.

Every time I try to deserialize a MessageObject on the server, I get an OutOfMemoryException.


First of all, here is the MessageObject class:

[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 is a child of the ReplicableObject . Here's the 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(); } } 

When the client is ready to send MessageObject to the server, this is the code that it uses:

 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"); 

As soon as the server receives the data, this method is called (this is where the exception is thrown):

 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; } 

Most of the above method is just looking for a TerminationString, so here are the important lines:

 MemoryStream ms = new MemoryStream(); ms.Write(byteString, 0, i - 10); ms.Position = 0; ReplicableObject ro = (ReplicableObject) Formatter.Deserialize(ms); ms.Close(); return ro; 

The line that fires "ReplicableObject ro =" throws an OutOfMemoryException. I do not understand how this can happen, especially considering that the objects that I submit are tiny.

I should point out that I am new to sending serialized data over the network, so maybe I did something wrong in this regard.

Please leave a comment if you need clarification. :)

Thanks.


Edit: Fix exception tracing on request:

mscorlib.dll! System.Runtime.Serialization.Formatters.Binary.BinaryObjectWithMap.Read (System.Runtime.Serialization.Formatters.Binary._BinaryParser input = {System.Runtime.Serialization.Formatters.Binary._BinaryParser}) + 0x4f bytes
mscorlib.dll! System.Runtime.Serialization.Formatters.Binary._BinaryParser.ReadObjectWithMap (System.Runtime.Serialization.Formatters.Binary.BinaryHeaderEnum binaryHeaderEnum) + 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.HeaderHandler handler = null, System.Runtime.Serialization.Formatters.Binary .__ BinaryParser serParser, bool fCheck, bool isCrossAppRomain .Remoting.Messaging.IMethodCallMessage methodCallMessage = null) + 0xaf bytes
mscorlib.dll! System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler, bool fCheck, bool isCrossAppDomain, System.Runtime.Remoting.Messaging.essageMallCall + IMageC 0xcf bytes
mscorlib.dll! System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream) + 0x10 bytes

HolotypeTwo.dll! HolotypeTwo.Engine.CheckByteStringForRO (byte [] byteString = {byte [8192]}) String 34 + 0x10 bytes C # HolotypeServer.exe! HolotypeServer.UnauthorisedPlayer.StartListening () String 27 + 0x8 bytes C # mscorlib.dll! System.Threading.ThreadHelper.ThreadStart_Context (state object) + 0x63 bytes
mscorlib.dll! System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executeContext, System.Threading.ContextCallback callback, state object, bool ignoreSyncCtx) + 0xb0 bytes
mscorlib.dll! System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executeContext, System.Threading.ContextCallback callback, object state) + 0x2c bytes
mscorlib.dll! System.Threading.ThreadHelper.ThreadStart () + 0x44 bytes

+4
source share
1 answer

Have you checked the contents of what you are trying to Deserialize? Due to lack of code, you could get two objects in the stream. The CheckByteStringForRO method may end up missing its end marker if the "e" bytes appear immediately before the marker. To correctly catch this case, there must be a condition for your else:

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

Also, why not just create a collection of your objects and serialize it instead of using terminal markers and all that?

0
source

Source: https://habr.com/ru/post/1369403/


All Articles