4

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

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

为什么 C# 默认不使用算术溢出检查?

在 C# 中处理整数溢出的最佳方法?

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

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

4

1 回答 1

4

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

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

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

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

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

当需要性能时,我会简单地使用未选中的块。

于 2014-01-31T09:21:33.483 回答