具有简单继承结构的Protobuf-net StackOverflowException

时间:2017-06-15 14:17:24

标签: c# protobuf-net

我正在研究一个使用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保持不变所需的包装器实例。

  1. 我在做傻事吗?
  2. 我是否必须在流中编写某种分隔符来分隔对象?
  3. 是否有更好的方法来编写和回读不同类型的数据包,同时允许AsReference工作?
  4. 我很感激您的任何见解。

    作为参考,这是异常时堆栈的一部分:

    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,但最新版本也会产生溢出。

0 个答案:

没有答案