简体   繁体   English

C#中算术溢出检查的最佳实践是什么?

[英]What are best practices for arithmetic overflow checking in C#?

There are some good articles on the web / stackoverflow about the usage of the 'checked' keyword vs. the compiler option 'Check for arithmetic overflow/underflow', like those: 关于'checked'关键字与编译器选项'Check for arithmetic overflow / underflow'的使用,web / stackoverflow上有一些很好的文章,如下所示:

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

Why doesn't C# use arithmetic overflow checking by default? 为什么C#默认不使用算术溢出检查?

Best way to handle Integer overflow in C#? 在C#中处理整数溢出的最佳方法是什么?

Still I don't know which one I should use. 我仍然不知道应该使用哪一个。 Per default I would prefer to go with the compiler option to be always safe, to not clutter my code with the unchecked keyword, not to forget it in some places and finally it is not very commonly used, so probably unknown to many developers. 默认情况下,我更喜欢使用编译器选项来保证安全,不要使用unchecked关键字混乱我的代码,不要忘记它在某些地方,最后它不是很常用,所以许多开发人员可能都不知道。

But then how bad is the actual performance hit I take? 但是,我采取的实际性能有多糟糕? I guess MS set the default not to do the overflow checking for a good reason. 我想MS设置默认不进行溢出检查是有充分理由的。 Does the compiler option only concern my code or also every consumed libraries and the framework itself? 编译器选项是仅涉及我的代码还是每个使用的库和框架本身?

I had the same question. 我有同样的问题。 I prefer piece of code to be checked by default in my company's code, because overflow side effects can cost a lot and be hard to diagnose. 我更喜欢在我公司的代码中默认检查一段代码,因为溢出副作用可能会花费很多而且难以诊断。 Discovering the real reason of those side effects can be every valuable. 发现这些副作用的真正原因可能是每一个有价值的。

The question is, what do we lose in terms of performance? 问题是,我们在绩效方面会失去什么?

Here is a very simple bench : 这是一个非常简单的工作台:

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);
}

In the generated IL, I see that the checked and unchecked keyword determines whether the add.ovf or add instruction will be used. 在生成的IL中,我看到checkedunchecked关键字确定是否将使用add.ovfadd指令。 (both for Debug and Release configs) (适用于Debug和Release配置)

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

Results (x64 host) 结果(x64主机)

Debug 调试

  • Unchecked: 2371 未选中:2371
  • Checked: 2437 检查:2437

Release 发布

  • Unchecked: 2088 未选中:2088
  • Checked: 2266 检查:2266

Other results by replacing long(s) by an int(s) (x64 host) 通过int(s)替换long(s)的其他结果(x64主机)

Debug 调试

  • Unchecked: 1665 未选中:1665
  • Checked: 1568 检查:1568

Release 发布

  • Unchecked: 189 未选中:189
  • Checked: 566 检查:566

The performance hit is there, it looks like it is more important to choose the right variable type that to go checked or unchecked. 性能受到影响,看起来选择要检查或取消选中的正确变量类型更为重要。 Anyway it doesn't change my opinion. 无论如何,它并没有改变我的观点。 I'll turn on the "Check for arithmetic overflow/underflow" in all our projects! 我将在所有项目中打开“检查算术溢出/下溢”! (Advanced Build Settings). (高级构建设置)。

When in need of performance, I'll simply use an unchecked block. 当需要性能时,我将简单地使用未经检查的块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM