gpt4 book ai didi

c# - Binaryformatter 序列化中的十进制字节数组构造函数

转载 作者:太空狗 更新时间:2023-10-29 21:50:35 25 4
gpt4 key购买 nike

我面临着一个我无法识别的非常棘手的问题。
我正在运行一个非常大的商业 ASP.Net 应用程序,其中包含数千个对象;它使用内存中的序列化/反序列化和 MemoryStream 来克隆应用程序的状态(保险契约(Contract))并将其传递给其他模块。多年来一直运作良好。现在有时,不是系统地,在序列化中它会抛出异常

Decimal byte array constructor requires an array of length four containing valid decimal bytes.

使用相同的数据运行相同的应用程序,5 次中有 3 次有效。我启用了所有 CLR 异常,Debug - Exceptions - CLR Exception - Enabled,所以我想如果发生错误的初始化/十进制字段赋值,程序应该停止。它不会发生。
我试图在更多基本对象中拆分序列化,但很难尝试识别导致问题的字段。从生产中的工作版本和我从 .Net 3.5 到 .NET 4.0 的这个版本,对 UI 部分而不是业务部分进行了一致的更改。我会耐心地检查所有更改。

char *p 写在不该写的地方时,它看起来像老式的 C 问题,只有在序列化过程中检查所有数据时问题才会出现。

在 .Net 的托管环境中是否可能发生这样的事情?该应用程序很大,但我看不到异常的内存增长。调试和跟踪问题的方法是什么?

下面是堆栈跟踪的一部分

[ArgumentException: Decimal byte array constructor requires an array of length four containing valid decimal bytes.]
System.Decimal.OnSerializing(StreamingContext ctx) +260

[SerializationException: Value was either too large or too small for a Decimal.]
System.Decimal.OnSerializing(StreamingContext ctx) +6108865
System.Runtime.Serialization.SerializationEvents.InvokeOnSerializing(Object obj, StreamingContext context) +341
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder) +448
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo) +969
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck) +1016
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck) +319
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph) +17
Allianz.Framework.Helpers.BinaryUtilities.SerializeCompressObject(Object obj) in D:\SVN\SUV\branches\SUVKendo\DotNet\Framework\Allianz.Framework.Helpers\BinaryUtilities.cs:98
Allianz.Framework.Session.State.BusinessLayer.BLState.SaveNewState(State state) in

对于冗长的故事和未确定的问题,我深表歉意,我将非常感谢任何帮助。

最佳答案

那是……非常有趣;那时候实际上并不是在读取或写入数据 - 它正在调用序列化前回调,又名 [OnSerializing],这里映射到 decimal.OnSerializingthat 所做的是尝试对这些位进行完整性检查 - 但看起来 BCL 中只是存在一个错误。这是 4.5 中的实现(咳嗽“反射器”咳嗽):

[OnSerializing]
private void OnSerializing(StreamingContext ctx)
{
try
{
this.SetBits(GetBits(this));
}
catch (ArgumentException exception)
{
throw new SerializationException(Environment.GetResourceString("Overflow_Decimal"), exception);
}
}

GetBits 获取 lo/mid/hi/flags 数组,因此我们可以非常确定传递给 SetBits 的数组是非空且长度正确的.所以要失败,必须失败的部分在 SetBits 中,此处:

private void SetBits(int[] bits)
{
....

int num = bits[3];
if (((num & 0x7f00ffff) == 0) && ((num & 0xff0000) <= 0x1c0000))
{
this.lo = bits[0];
this.mid = bits[1];
this.hi = bits[2];
this.flags = num;
return;
}
throw new ArgumentException(Environment.GetResourceString("Arg_DecBitCtor"));
}

基本上,如果 if 测试通过,我们就会进入,分配值,然后成功退出;如果 if 测试失败,它最终会抛出异常。 bits[3]flags block ,它包含符号和比例,IIRC。所以这里的问题是:您如何获得带有损坏的 flags block 的无效 decimal

引自MSDN:

The fourth element of the returned array contains the scale factor and sign. It consists of the following parts: Bits 0 to 15, the lower word, are unused and must be zero. Bits 16 to 23 must contain an exponent between 0 and 28, which indicates the power of 10 to divide the integer number. Bits 24 to 30 are unused and must be zero. Bit 31 contains the sign: 0 mean positive, and 1 means negative.

所以要通过这个测试:

  • 指数无效(在0-28之外)
  • 低位字非零
  • 高字节(不包括MSB)非零

不幸的是,我没有找到哪个 decimal 无效的神奇方法...

我能想到的唯一方法是:

  • 在整个代码中散布 GetBits/new decimal(bits) - 可能作为 void SanityCheck(this decimal) 方法(可能带有[Conditional("DEBUG")] 之类的)
  • [OnSerializing] 方法添加到您的主域模型中,该方法记录在某处(可能是控制台),以便您可以看到它在爆炸时正在处理的对象

关于c# - Binaryformatter 序列化中的十进制字节数组构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18142301/

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