带枚举的Protobuf-net反序列化异常

本文关键字:反序列化 异常 Protobuf-net 枚举 | 更新日期: 2023-09-27 17:49:49

我有一个带有标志的enum,我用[ProtoMember]属性来装饰,该属性可以在运行Win7 x64的本地机器上序列化

和反序列化

然而,我的用例涉及到在运行Windows server 2008 R2 Enterprise 64位的服务器上进行序列化,并在我的本地机器上进行反序列化。当我反序列化时,我得到了异常:"Overflow exception was unhandled;算术运算导致溢出"。它似乎是从ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer抛出的。读取(对象值,ProtoReader源).

我尝试将枚举更改为int并在服务器上序列化

/本地反序列化工作。我想使用enum而不是int。我做错了什么?

不确定这是否是相关信息,但是我在服务器上运行的可执行文件是在我的本地机器上构建的。

枚举来自引用的外部dll。当我在我的解决方案中复制枚举代码时,反序列化工作。只有当我使用来自外部dll的枚举(我怀疑源代码未知)并且枚举值大于(似乎)128时才会抛出异常。在我的例子中,是Status。泽塔和状态。都抛出了异常;正确反序列化的其他枚举值。枚举定义如下:

[Flags]
public enum Status
{
    None = 0,
    Alpha = 1,
    Beta = 8,
    Gamma = 16,
    Delta = 32,
    Epsilon = 64,
    Zeta = 132,
    All = 255,
}

我不能更改dll中的代码。我该怎么做呢?我需要.proto文件吗?如果可能的话,我会尽量避免这种情况。

带枚举的Protobuf-net反序列化异常

这只影响: byte

的枚举

分析!发现脑死亡错误:

case ProtoTypeCode.SByte: Emit(OpCodes.Conv_Ovf_U1); break;
case ProtoTypeCode.Byte: Emit(OpCodes.Conv_Ovf_I1); break;

这将在今天晚些时候被撤销并部署。谢谢。

解释一下:byte是无符号的(0到255),sbyte是有符号的(-128到127);Conv_Ovf_U1基本上是IL"转换为byte,检查溢出"(就像c#中的checked关键字如何工作),Conv_Ovf_I1是"转换为sbyte,检查溢出"。因此,任何超过127的值都会触发溢出标志,导致异常。

这确实有点奇怪。CLR中可能存在影响ProtoBuf的差异(例如,CLR附带了许多不同的gc)。比较机器。来自两台机器的配置文件可能会暴露一些差异。

为了解决这个问题,你可以尝试用ProtoContract标记枚举本身,用ProtoMember标记每个枚举成员。后者允许您设置一个Value属性供ProtoBuf使用。您也可以将DataFormat设置为Fixed,看看是否比默认的效果更好。

你可以在这里找到一些例子