Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 基于整数溢出的GCC优化_C++_C_Gcc_Compiler Optimization_Integer Overflow - Fatal编程技术网

C++ 基于整数溢出的GCC优化

C++ 基于整数溢出的GCC优化,c++,c,gcc,compiler-optimization,integer-overflow,C++,C,Gcc,Compiler Optimization,Integer Overflow,最近我讨论了一个问题,有人想检查签名int溢出,就像这样if(a+B

最近我讨论了一个问题,有人想检查签名int溢出,就像这样
if(a+B<2*max(a,B))
。让我们先忽略一下逻辑本身是错误的,然后在C/C++上下文中讨论带符号整数溢出。(我相信这部分标准完全继承了C)

当前ish GCC将优化哪些需要有符号整数溢出的检查,哪些不会

由于原文没有那么好的表述,而且显然有争议,我决定稍微修改一下问题,但将原文保留在下面。

下面使用的所有示例都是测试gcc版本
4.7.2(Debian 4.7.2-5)
,并使用
-O3

也就是说,它是未定义的,GCC臭名昭著地使用它来执行一些分支简化。我想到的第一个例子是

这会产生一个无限循环。这种优化的另一种情况是

它触发了你所期望的用2的补码表示的分支。类似地,此代码保持条件分支不变

int C=abs(A);
如果(A+C<0){
/*为了达到这个目的,必须发生溢流或下溢*/
}

现在,对于这个问题,是否有一种模式大致类似于
if(a+B
if(a+B
,将被优化掉?当我在写这篇文章之前在谷歌上搜索时,似乎最后一个代码段应该被优化掉,但我无法在不显式使用常量的溢出检查中重现这种错误。

许多编译器会将包含有符号整数或指针的表达式替换为“false”,如


没有未定义的行为(不带64位整数或32位指针)

请允许我转述一下你的问题,我相信你会问这样的问题

是否存在这样一种编译器,它能如此积极地优化有符号整数表达式,以至于它准备对此类表达式的某些类别进行详细分析,以确定相关条件为真(或假)在表达式结果的类型
的可表示值的整个
范围内,并通过这些方法删除条件测试

您提供的编译器是GCC的一个特定版本,您提供的表达式属于一个狭窄的范围,但我假设您也有兴趣了解另一个编译器或密切相关的表达式

答案是现在我还不知道,但这可能只是时间问题

现有编译器对包含常量或某些可识别模式的表达式执行过早求值,如果在求值过程中遇到未定义的行为,通常会避免优化表达式。他们没有义务这样做

数据流分析是CPU和内存密集型的,并且倾向于在有很大好处的地方使用。最后,C++标准将停止变化(如此之多),编译器编写者将有时间在他们的手中。编译器读取质数筛程序并将其优化为单个打印语句的日子还有点短,但它会到来


我的答案主要是指出这实际上是一个关于编译器技术的问题,与C++标准没有什么关系。也许你应该直接问GCC小组。

你的最后一个例子比其他例子复杂得多。它需要通过一个函数调用来跟踪a和C之间的依赖关系,以及在其他函数已经需要的基础上对该函数的“数学理解”。我真的不明白你到底想要什么。“看起来大致像这样”有点含糊不清,因为它是未定义的行为,所以任何答案都是有效的。@KerrekSB我认为这是臭名昭著的,因为试图检查溢出以防止恶意用户弄乱东西,会以加快代码速度的名义得到优化。老实说,我认为标准的这一部分是一个巨大的混乱(这可以通过让它实现定义而不是未定义来防止)。@Xarn我能说的就是你错了。事实上,对于在无符号类型的情况下定义行为,有很多反对意见;在某些体系结构上,已定义的行为具有显著的运行时成本。有些体系结构确实(或者至少确实)存在溢出陷阱,这也是造成这种未定义行为的一个重要原因。对于指针来说是不可能的。指针算法未定义在数组的边界之外。@R..:可能有一个数组的大小太大,无法放入
uint32\u t
,在这种情况下,指定的表达式不会包含任何UB。感谢您的回答,但实际问题有所不同(仔细考虑后,我在OP中正确地表述了它).似乎是同一个问题,但你只限于GCC。我的答案(最后一段)更为正确。
int i = 1;
while (i > 0){
    i *= 2;
}
if (A + 2 < A){
    /* Handle potential overflow */
}
if (INT_MAX + 1 < 0){
    /* You wouldn't write this explicitly, but after static analysis the program
       could be shown to contain something like this. */
}
int C = abs(A);
if (A + C < 0){
    /* For this to be hit, overflow or underflow had to happen. */
}
a + 1 < a // signed integer a
p + 1 < p // Pointer p
for (char* q = p; q < p + 2; ++q) ...
if (A + abs (A) < 0)
&p [i] > &p [i+1]