【问题标题】:What are best practices for arithmetic overflow checking in C#?C# 中算术溢出检查的最佳实践是什么?
【发布时间】:2013-10-07 12:56:51
【问题描述】:

在网络/stackoverflow 上有一些关于“checked”关键字的使用与编译器选项“检查算术上溢/下溢”的好文章,例如:

http://www.codethinked.com/c-trivia-what-no-overflow

Why doesn't C# use arithmetic overflow checking by default?

Best way to handle Integer overflow in C#?

我仍然不知道我应该使用哪一个。默认情况下,我宁愿使用编译器选项以确保始终安全,不要用 unchecked 关键字弄乱我的代码,不要在某些地方忘记它,最后它不是很常用,所以可能许多开发人员都不知道。

但是,我所受到的实际性能影响有多严重?我猜 MS 设置默认不进行溢出检查是有充分理由的。编译器选项是否只涉及我的代码或每个使用的库和框架本身?

【问题讨论】:

  • 我也很想知道 unchecked 是默认值的原因。人们经常声称这是出于性能原因,但我看到有关实际性能影响的相互矛盾的报告。有人说它很重要,有人说它难以察觉。
  • 开启检查,并担心 Profiler 告诉您何时何地检查的速度。

标签: c# compiler-construction overflow keyword checked


【解决方案1】:

我也有同样的问题。我更喜欢在我公司的代码中默认检查一段代码,因为溢出的副作用可能会花费很多并且难以诊断。发现这些副作用的真正原因可能非常有价值。

问题是,我们在性能方面损失了什么?

这是一个非常简单的长凳:

static void Main(string[] args)
{
    long c = 0;
    var sw = new Stopwatch();
    sw.Start();
    unchecked
    {
        for (long i = 0; i < 500000000; i++) c += 1;
    }
    sw.Stop();
    Console.WriteLine("Unchecked: " + sw.ElapsedMilliseconds);

    c = 0;
    sw.Restart();
    checked
    {
        for (long i = 0; i < 500000000; i++) c += 1;
    }
    sw.Stop();
    Console.WriteLine("Checked: " + sw.ElapsedMilliseconds);
}

在生成的 IL 中,我看到 checkedunchecked 关键字决定是 add.ovf 还是 add 指令将被使用。 (用于调试和发布配置)

IL_001c:  ldloc.2
IL_001d:  ldc.i4.1
IL_001e:  conv.i8
IL_001f:  add


IL_0066:  ldloc.2
IL_0067:  ldc.i4.1
IL_0068:  conv.i8
IL_0069:  add.ovf

结果(x64 主机)

调试

  • 未选中:2371
  • 已检查:2437

发布

  • 未选中:2088
  • 已检查:2266

将 long(s) 替换为 int(s) 的其他结果(x64 主机)

调试

  • 未选中:1665
  • 已检查:1568

发布

  • 未选中:189
  • 已检查:566

性能影响就在那里,看起来更重要的是选择正确的变量类型来检查或取消检查。无论如何,这不会改变我的看法。我将在我们所有的项目中打开“检查算术上溢/下溢”! (高级构建设置)。

当需要性能时,我会简单地使用 unchecked 块。

【讨论】:

  • 仅供参考,其他类型(例如十进制)的性能损失看起来相似。或者用乘法...
猜你喜欢
  • 2017-04-28
  • 1970-01-01
  • 2011-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-07
  • 1970-01-01
相关资源
最近更新 更多