gpt4 book ai didi

c# - 我在反序列化过程中遇到下一个异常 : "Invalid field in source data: 0". 如何找出源代码中的原因/错误位置?

转载 作者:太空宇宙 更新时间:2023-11-03 13:54:50 29 4
gpt4 key购买 nike

在这个函数中,我尝试在客户端反序列化 class Simulator:

private void OnHandshakeSimulationStart(Peer peer, Message msg, int seq)
{
System.Diagnostics.Trace.WriteLine("TRY OnHandshakeSimulationStart id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
try
{
HandshakeSimulationStart simstart = msg as HandshakeSimulationStart;
if (simstart == null) OnHandshakeFailed();
System.Diagnostics.Trace.WriteLine("#1.1 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);

//Simulator sim = (Simulator)simstart.SimulationState.GetObject();
Simulator sim = null;
System.Diagnostics.Trace.WriteLine("#1.2 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);

try
{
// sim = (Simulator)simstart.SimulationState.GetObject();
using (MemoryStream ms = (MemoryStream)simstart.SimulationState.GetObjectWoDeserialize())
{
System.Diagnostics.Trace.WriteLine("#2.1 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
ms.Seek(0, SeekOrigin.Begin);
System.Diagnostics.Trace.WriteLine("#2.2 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
sim = Serializer.Deserialize<Simulator>(ms); //(Simulator)new BinaryFormatter().Deserialize(ms);
System.Diagnostics.Trace.WriteLine("#2.3 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
}
catch (SerializationException e)
{
Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
}

System.Diagnostics.Trace.WriteLine("#3 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
sim.PostDeserialize();
System.Diagnostics.Trace.WriteLine("#4 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
lock (this)
{
simulator = sim;
// команды полученные до этого ставим в очередь
foreach (Commands.Command cmd in CollectedCommandsDuringHandshake)
if (cmd.tact >= simulator.tactCounter)
simulator.InternalQueue(cmd);
System.Diagnostics.Trace.WriteLine("#5 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
CollectedCommandsDuringHandshake = null;

// настраиваем сетевое время
networkTime = new Network.Timer(simulator.HZ);
// настраиваем обработчик команд
simulator.OnAfterCommand.Add(typeof(Commands.Command), new CommandHandler(OnAfterCommand));
System.Diagnostics.Trace.WriteLine("#6 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
// хендшейк закончен
OnHandshakeCompleted();
System.Diagnostics.Trace.WriteLine("#7 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
CurrentReceiveHandler = new Peer.MessageReceivedHandler(OnMessageReceivedInActiveState);
System.Diagnostics.Trace.WriteLine("#8 id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
}
catch (Exception exception)
{
System.Diagnostics.Trace.WriteLine("OnHandshakeSimulationStart ERROR: " + exception.Message + " id = " + +System.Threading.Thread.CurrentThread.ManagedThreadId);
}
}

通过使用 DebugView.exe 应用程序,我得到:

[26480] Client handshaked: id=0 name=ECDIS[1] version=3.8.1 
[26480] ObjectWrapper(object obj) - ms.Length = 67 id = 10
[26480] Write(Network.Packet packet) - ObjectDumpProtoBuf.Length = 256 id = 10
[25404] ObjectWrapper(Network.Packet packet) - len = 256 id = 5
[25404] TRY OnHandshakeSimulationStart id = 5
[25404] #1.1 id = 5
[25404] #1.2 id = 5
[25404] GetObjectWoDeserialize() id = 5
[25404] #2.1 id = 5
[25404] #2.2 id = 5
[25404] OnHandshakeSimulationStart ERROR: Invalid field in source data: 0 id = 5

我发现在反序列化 class Simulator 期间引发了异常:

namespace Trainer
{
[Serializable]
[ProtoContract]
public class Simulator
{

[ProtoMember(1)]
public IDictionary<int, Task> tasks = new Dictionary<int, Task>();

[ProtoMember(2)]
public Workplace[] workplaces;

[ProtoMember(3)]
public int tactCounter = 0;

[ProtoMember(4)]
public int tactLimit = 0;

[NonSerialized]
public int sheduleLimit = 0;

[ProtoMember(5)]
public int HZ = 100;

public int SyncFactor { get { return 1; } } // HZ/8

public double DT { get { return 1.0 / (double)HZ; } }

[ProtoMember(6)]
List<Commands.Command> commandQueue = new List<Commands.Command>();
//Queue commandQueue = new Queue();

[NonSerialized]
public CommandEventTable OnBeforeCommand = new CommandEventTable();

[NonSerialized]
public CommandEventTable OnAfterCommand = new CommandEventTable();

public void PostDeserialize()
{
OnBeforeCommand = new CommandEventTable();
OnAfterCommand = new CommandEventTable();
foreach (Task t in tasks.Values)
t.PostDeserialize();
}

public Simulator()
{

}

//there are also a lot of functions...

}

一个对象包装器有助于序列化/反序列化,它可以很好地与 binaryformatter 一起工作,但我将其更改为使用 protobuf-net:

namespace Trainer.Network
{
[Serializable]
[ProtoContract]
public class ObjectWrapper : IFile
{
//public byte[] ObjectDump;

[ProtoMember(1)]
public byte[] ObjectDumpProtoBuf;

public ObjectWrapper(object obj)
{
using (MemoryStream ms = new MemoryStream())
{
//for protobuf-net:
Serializer.Serialize(ms, obj);
ObjectDumpProtoBuf = ms.GetBuffer();

//for binaryformatter:
//new BinaryFormatter().Serialize(ms,obj);
//ObjectDump = ms.GetBuffer();

_Guid = Guid.NewGuid();

System.Diagnostics.Trace.WriteLine("ObjectWrapper(object obj) - ms.Length = " + ms.Length + " id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
}

public ObjectWrapper(Network.Packet packet)
{
bool body = packet.ReadBool();
if (body)
{
int len = packet.ReadInt();
ObjectDumpProtoBuf = (byte[])packet.Read(typeof(byte), len);
//ObjectDump = (byte[])packet.Read(typeof(byte),len);

System.Diagnostics.Trace.WriteLine("ObjectWrapper(Network.Packet packet) - len = " + len + " id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
else
_Guid = (Guid)packet.Read(typeof(Guid));

}

public void Write(Network.Packet packet)
{
System.Diagnostics.Trace.WriteLine("Write(Network.Packet packet) - ObjectDumpProtoBuf.Length = " + ObjectDumpProtoBuf.Length + " id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
packet.Write(true);

//packet.Write((int)ObjectDump.Length);
//packet.Write(ObjectDump);
packet.Write((int)ObjectDumpProtoBuf.Length);
packet.Write(ObjectDumpProtoBuf);
}

public void WriteFileRef(Network.Packet packet)
{
packet.Write(false);
packet.Write(Guid);
}

public object GetObject()
{
//using (MemoryStream ms = new MemoryStream(ObjectDump))
using (MemoryStream ms = new MemoryStream(ObjectDumpProtoBuf))
return new BinaryFormatter().Deserialize(ms);
}

public MemoryStream GetObjectWoDeserialize()
{
System.Diagnostics.Trace.WriteLine("GetObjectWoDeserialize() id = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
return new MemoryStream(ObjectDumpProtoBuf);
}

#region IFile Members

[ProtoMember(2)]
public Guid _Guid = new Guid();
public Guid Guid { get { return _Guid; } }

public byte[] Data
{
//get { return ObjectDump; }
//set { ObjectDump = value;}
get { return ObjectDumpProtoBuf; }
set { ObjectDumpProtoBuf = value; }
}
#endregion
}

问题:如何找出问题的确切位置?我的意思是“源数据中的无效字段:0”源数据 0 是什么?这是一个

   [ProtoMember(1)]
public IDictionary<int, Task> tasks = new Dictionary<int, Task>();

还是不行?所以我不明白哪里出了问题......

最佳答案

开始吧:

ObjectDumpProtoBuf = ms.GetBuffer();

这为您提供了超大 后备缓冲区。如果您想避免内存复制,这很方便,但是您需要非常小心,只处理 ms.Length字节 - 其余的都是垃圾。特别是,由于您还没有使用该内存,它会全为零...零不是有效的字段标题,并且会导致您看到的错误。

要快速检查是否是问题所在,请将其替换为:

ObjectDumpProtoBuf = ms.ToArray();

这是缓冲区中数据的大小合适副本。

如果可行,您可能想要切换为返回 ArraySegment<byte>或类似表示超大缓冲区的部分;即

new ArraySegment<byte>(ms.GetBuffer(), 0, (int)ms.Length);

你用 BinaryFormatter 逃脱惩罚的原因是那个BinaryFormatter知道自己的长度。 Protocol buffers 是一种可追加格式,因此它不知道自己的长度。

关于c# - 我在反序列化过程中遇到下一个异常 : "Invalid field in source data: 0". 如何找出源代码中的原因/错误位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12601164/

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