检测C / C ++整数溢出没有有用和可靠的方式? [英] No useful and reliable way to detect integer overflow in C/C++?

查看:139
本文介绍了检测C / C ++整数溢出没有有用和可靠的方式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能重复:结果
  检测C / C整数溢出的最佳方式++


不,这不是重复。问题是相同的,但问题是不同的。

gcc编译器可以优化掉溢出检查(与-O2),例如:

The gcc compiler can optimize away an overflow check (with -O2), for example:

int a, b;
b = abs(a);                     // will overflow if a = 0x80000000
if (b < 0) printf("overflow");  // optimized away

gcc的人认为,这是不是一个错误。溢出是未定义的行为,按照C标准,它允许编译器做的任何的。显然,的任何的包括假设溢出从未发生过。不幸的是,这允许编译器优化掉的溢出检查。

The gcc people argue that this is not a bug. Overflow is undefined behavior, according to the C standard, which allows the compiler to do anything. Apparently, anything includes assuming that overflow never happens. Unfortunately, this allows the compiler to optimize away the overflow check.

要检查溢出的安全方式在最近的<一个被描述href=\"https://www.securecoding.cert.org/confluence/display/sec$c$c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow\">CERT纸。本文建议这样做增加了两个整数之前是这样的:

The safe way to check for overflow is described in a recent CERT paper. This paper recommends doing something like this before adding two integers:

if ( ((si1^si2) | (((si1^(~(si1^si2) & INT_MIN)) + si2)^si2)) >= 0) { 
  /* handle error condition */
} else {
  sum = si1 + si2;
}

显然,你必须做这样的事情每前+, - 当你想,以确保结果是有效的,*,/等操作在一系列的计算。例如,如果你想确保数组索引是不是出界。这是如此繁琐,几乎没有人这样做。至少我从来没有见过一个C / C ++的程序,做这个系统的。

Apparently, you have to do something like this before every +, -, *, / and other operations in a series of calculations when you want to be sure that the result is valid. For example if you want to make sure an array index is not out of bounds. This is so cumbersome that practically nobody is doing it. At least I have never seen a C/C++ program that does this systematically.

现在,这是一个根本性的问题:

Now, this is a fundamental problem:


  • 检查数组索引前访问该阵列是有用的,但并不可靠。

  • Checking an array index before accessing the array is useful, but not reliable.

检查在一系列的计算与CERT方法每次运行可靠,但没有用。

Checking every operation in the series of calculations with the CERT method is reliable but not useful.

结论:有检查在C / C ++溢出没有有用和可靠的方式

Conclusion: There is no useful and reliable way of checking for overflow in C/C++!

我不相信标准的写入时此意。

I refuse to believe that this was intended when the standard was written.

我知道有一些可以解决问题的某些命令行选项,但这并不能改变一个事实,即我们有标准或它目前除pretation一个根本性的问题。

I know that there are certain command line options that can fix the problem, but this doesn't alter the fact that we have a fundamental problem with the standard or the current interpretation of it.

现在我的问题是:
是gcc的人服用的未定义行为过犹不及,当它使他们能够优化掉溢出检查,或者是C / C ++标准坏了?

Now my question is: Are the gcc people taking the interpretation of "undefined behavior" too far when it allows them to optimize away an overflow check, or is the C/C++ standard broken?

添加了注意事项:
对不起,你可能误解了我的问题。我不问如何解决的问题 - 已回答<一个href=\"https://www.securecoding.cert.org/confluence/display/sec$c$c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow\">elsewhere.我问的是C标准一个更根本的问题。如果没有检查溢出没有有用和可靠的方式,然后语言本身是可疑的。例如,如果我做一个安全数组类与当时的边界检查,我应该是安全的,但我不是,如果边界检查可以被优化掉。

Added note: Sorry, you may have misunderstood my question. I am not asking how to work around the problem - that has already been answered elsewhere. I am asking a more fundamental question about the C standard. If there is no useful and reliable way of checking for overflow then the language itself is dubious. For example, if I make a safe array class with bounds checking then I should be safe, but I'm not if the bounds checking can be optimized away.

如果该标准允许这种情况发生那么无论是标准需要修订或标准间pretation需要修正。

If the standard allows this to happen then either the standard needs revision or the interpretation of the standard needs revision.

补充说明2:
这里的人们似乎不愿意讨论未定义行为概念的质疑。该C99标准列出了191种不同的未定义行为(链接)其实是一个草率的标准的指示。

Added note 2: People here seem unwilling to discuss the dubious concept of "undefined behavior". The fact that the C99 standard lists 191 different kinds of undefined behavior (link) is an indication of a sloppy standard.

许多程序员容易接受未定义的行为给牌做任何事情,包括格式化硬盘的声明。我认为这是该标准把整数溢出到相同的危险类别作为写作之外数组边界问题。

Many programmers readily accept the statement that "undefined behavior" gives the license to do anything, including formatting your hard disk. I think it is a problem that the standard puts integer overflow into the same dangerous category as writing outside array bounds.

为什么这两种未定义行为有什么不同?这是因为:

Why are these two kinds of "undefined behavior" different? Because:


  • 许多程序依赖于整数溢出是良性的,但有些程序依赖于书写之外数组边界,当你不知道什么是存在的。

  • Many programs rely on integer overflow being benign, but few programs rely on writing outside array bounds when you don't know what is there.

写作之外数组边界实际的 的可以做的那么糟糕,因为格式化你的硬盘(至少在类似DOS的一个不受保护的操作系统)的东西,大多数程序员都知道,这是危险的。

Writing outside array bounds actually can do something as bad as formatting your hard disk (at least in an unprotected OS like DOS), and most programmers know that this is dangerous.

当你把整数溢出进入危险的怎么都行的范畴,它可以让编译器做任何事,包括说谎关于它在做什么(在溢出检查优化掉的情况下)

When you put integer overflow into the dangerous "anything goes" category, it allows the compiler to do anything, including lying about what it is doing (in the case where an overflow check is optimized away)

如写之外数组边界错误可以使用调试器中,但优化掉溢出检查不能,因为优化通常是关闭调试时的错误。

An error such as writing outside array bounds can be found with a debugger, but the error of optimizing away an overflow check cannot, because optimization is usually off when debugging.

gcc编译器显然从不闻不问怎么都行的政策整数溢出的情况。有它自例如优化不闻不问许多情况下,一个循环,除非它可以验证溢出是不可能的。出于某种原因,海湾合作委员会的人已经认识到,如果他们遵循怎么都行的政策在这里我们有太多的失误,但他们有一个不同的态度,以优化掉溢出检查的问题。

The gcc compiler evidently refrains from the "anything goes" policy in case of integer overflow. There are many cases where it refrains from optimizing e.g. a loop unless it can verify that overflow is impossible. For some reason, the gcc people have recognized that we would have too many errors if they followed the "anything goes" policy here, but they have a different attitude to the problem of optimizing away an overflow check.

这也许不是讨论这些哲学问题的正确的地方。至少,大多数的答案这里有过的程度。有没有更好的地方来讨论呢?

Maybe this is not the right place to discuss such philosophical questions. At least, most answers here are off the point. Is there a better place to discuss this?

推荐答案

GCC开发是完全正确的位置。当标准说,行为是不确定的,这意味着恰好有在编译器的要求。

The gcc developers are entirely correct here. When the standard says that the behavior is undefined that means exactly that there are no requirements on the compiler.

作为一个有效的程序不能做任何导致UB(因为那就不再有效),编译器可以很好地认为UB不会发生。如果它仍然没有,什么编译器将是确定的。

As a valid program can not do anything that causes UB (as then it would not be valid anymore), the compiler can very well assume that UB doesn't happen. And if it still does, anything the compiler does would be ok.

有关您的问题有溢水口,一种解决方案是要考虑caclulations都应该办理什么范围。例如,平衡我的银行帐户时,我可以假设的金额将远低于1十亿,所以32位int会工作。

For your problem with overflow, one solution is to consider what ranges the caclulations are supposed to handle. For example, when balancing my bank account I can assume that the amounts would be well below 1 billion, so a 32-bit int will work.

有关你的应用领域你也许可以做些类似的预测准确的其中的溢出是可能的。然后你就可以在这些点上添加支票或选择其他数据类型(如果可用)。

For your application domain you can probably do similar estimates about exactly where an overflow could be possible. Then you can add checks at those points or choose another data type, if available.

这篇关于检测C / C ++整数溢出没有有用和可靠的方式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆