我正在研究一个使用protobuf-net将数据包写入流的系统,但我遇到了一个问题。
我设法将有问题的代码提炼为:
[TestFixture]
public static class ProtoTest {
[ProtoContract]
public class RootType {
[ProtoMember(1)] public ChildBase child;
}
[ProtoContract]
[ProtoInclude(10, typeof(Child1))]
[ProtoInclude(20, typeof(Child2))]
public class ChildBase {
[ProtoMember(1)] public int none;
}
[ProtoContract]
public class Child1 : ChildBase {
}
[ProtoContract]
public class Child2 : ChildBase {
}
[Test]
public static void Crashtest() {
var root = new RootType();
var writerStream = new MemoryStream();
var readerStream = new MemoryStream();
var writer = new ProtoWriter(writerStream, RuntimeTypeModel.Default, new SerializationContext());
var reader = new ProtoReader(readerStream, RuntimeTypeModel.Default, new SerializationContext());
root.child = new Child1();
RuntimeTypeModel.Default.Serialize(writer, root);
// Removing this line will allow the code to run properly
root.child = new Child2();
RuntimeTypeModel.Default.Serialize(writer, root);
writerStream.WriteTo(readerStream);
readerStream.Position = 0;
// This call will produce the exception
var firstChild = ((RootType)RuntimeTypeModel.Default.Deserialize(reader, null, typeof(RootType))).child;
Assert.NotNull(firstChild, "first child");
Assert.AreEqual(typeof(Child1), firstChild.GetType());
var secondChild = ((RootType)RuntimeTypeModel.Default.Deserialize(reader, null, typeof(RootType))).child;
Assert.NotNull(secondChild, "second child");
Assert.AreEqual(typeof(Child2), secondChild.GetType());
}
}
这将产生StackOverflowException
并使NUnit测试运行器崩溃。
ChildBase
将是我的数据包的基类,而RootType
是protobuf-net保持不变所需的包装器实例。
AsReference
工作?我很感激您的任何见解。
作为参考,这是异常时堆栈的一部分:
protobuf-net.dll!ProtoBuf.Meta.RuntimeTypeModel.GetKey(System.Type type, bool demand, bool getBaseKey) Line 718 + 0xffffffd4 bytes C#
protobuf-net.dll!ProtoBuf.Meta.RuntimeTypeModel.GetKeyImpl(System.Type type) Line 711 + 0x10 bytes C#
protobuf-net.dll!ProtoBuf.Meta.TypeModel.GetKey(ref System.Type type) Line 1224 + 0x10 bytes C#
protobuf-net.dll!ProtoBuf.Meta.TypeModel.SerializeCore(ProtoBuf.ProtoWriter writer, object value) Line 183 + 0xc bytes C#
protobuf-net.dll!ProtoBuf.Meta.TypeModel.Serialize(System.IO.Stream dest, object value, ProtoBuf.SerializationContext context) Line 218 C#
protobuf-net.dll!ProtoBuf.ProtoReader.Merge(ProtoBuf.ProtoReader parent, object from, object to) Line 1337 C#
[Lightweight Function]
protobuf-net.dll!ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(object value, ProtoBuf.ProtoReader source) Line 57 + 0x1a bytes C#
protobuf-net.dll!ProtoBuf.Meta.RuntimeTypeModel.Deserialize(int key, object value, ProtoBuf.ProtoReader source) Line 775 + 0xf bytes C#
protobuf-net.dll!ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoBuf.ProtoReader reader, System.Type type, object value, bool noAutoCreate) Line 700 + 0x14 bytes C#
protobuf-net.dll!ProtoBuf.Meta.TypeModel.Deserialize(System.IO.Stream source, object value, System.Type type, ProtoBuf.SerializationContext context) Line 589 + 0x14 bytes C#
protobuf-net.dll!ProtoBuf.Meta.TypeModel.Deserialize(System.IO.Stream source, object value, System.Type type) Line 566 + 0x14 bytes C#
protobuf-net.dll!ProtoBuf.ProtoReader.Merge(ProtoBuf.ProtoReader parent, object from, object to) Line 1338 + 0x13 bytes C#
[Lightweight Function]
protobuf-net.dll!ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read(object value, ProtoBuf.ProtoReader source) Line 57 + 0x1a bytes C#
protobuf-net.dll!ProtoBuf.Meta.RuntimeTypeModel.Deserialize(int key, object value, ProtoBuf.ProtoReader source) Line 775 + 0xf bytes C#
....
请注意,我正在运行r668,因为那是我的.pdb,但最新版本也会产生溢出。