【问题标题】:Bug in System.Random constructor?System.Random 构造函数中的错误?
【发布时间】:2009-07-23 03:14:56
【问题描述】:

System.Threading.ConcurrentQueue.TryDequeue 方法前几天抛出了一个异常,这让我大吃一惊。这是堆栈跟踪:

System.OverflowException: Negating the minimum value of a twos complement number is invalid.
   at System.Math.AbsHelper(Int32 value)
   at System.Random..ctor(Int32 Seed)
   at System.Threading.Collections.ConcurrentQueue`1.TryDequeueCore(T& result)
   at System.Threading.Collections.ConcurrentQueue`1.TryDequeue(T& result)
   at MyProgram.ThreadProc() in c:\MyProgram\Main.cs:line 118
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

起初我认为问题在于TryDequeueCore 调用了具有错误值的Random 构造函数。但进一步调查显示TryDequeueCore 调用了默认构造函数。在我看来,错误出现在 Random 构造函数中:

.method public hidebysig specialname rtspecialname 
        instance void  .ctor() cil managed
{
  // Code size       12 (0xc)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  call       int32 System.Environment::get_TickCount()
  IL_0006:  call       instance void System.Random::.ctor(int32)
  IL_000b:  ret
} // end of method Random::.ctor

正如System.Environment.TickCount 属性的文档所说:

这个属性的值是派生出来的 从系统定时器,并存储为 一个 32 位有符号整数。最后, 如果系统连续运行, TickCount 将从零递增到 Int32..::.MaxValue 大约为 24.9天,然后跳转到Int32..::.MinValue,这是一个 负数,然后递增 在接下来的 24.9 天内归零。

因此,如果您在那一毫秒期间(在系统启动 int.MaxValue 毫秒之后)调用 Random 构造函数,它将抛出此异常。

有人有解决方法吗?对于我自己的代码,我可以创建一个CreateRandom 方法来获取TickCount 值并检查它是否有int.MinValue。但是我无法控制的代码怎么办?

我希望 RTL​​ 团队在 .NET 4.0 中修复此问题。

2009 年 7 月 22 日更新:BCL 团队回应了该错误并表示已在下一个版本中解决。

【问题讨论】:

  • 我希望你提交错误报告 :)
  • 哇,很好的调查。
  • Microsoft Connect 上报告的错误。 connect.microsoft.com/VisualStudio 错误 #475447。
  • 实际上,我的错误报告是#475446。其他人将其报告为 475447。

标签: c# .net


【解决方案1】:

try/catch 并在毫秒后重试似乎是在修复此错误之前唯一可以做的事情。

【讨论】:

  • 也许吧。但是以 ConcurrentQueue.TryDequeue 为例。该方法根本不应该抛出异常。我现在必须将所有对 TryDequeue 的调用包装在 try/catch 块中。而我不知道的代码使用 Random 呢?
  • 只要在系统库的深处存在一个错误,它会导致在不应该抛出异常的情况下抛出异常,你还能用你无法控制的其他代码做什么来源,哪个可能会调用有问题的系统库?除非您可以切换到开源堆栈,一旦发现错误就可以在其中修复错误,否则您不可避免地会受到专有代码供应商的摆布。 try/catch 几乎是你唯一能做的事情,而且它绝对不是完美的,但是,还有什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-24
  • 2018-11-15
  • 2012-07-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-13
相关资源
最近更新 更多