优化的 clang 处理溢出
Optimized clang handling overflow
我有一些我的优化器没有预料到的奇怪行为。基本上这是一个变量溢出的情况,我试图用来处理它的逻辑正在中断。
这是完整的程序 (weird.cpp
):
#include <stdio.h>
class Example {
public:
void Change() {
change_count_++;
// Check for overflow. If it does, set to 1 which is still valid
if(change_count_ <= 0) {
change_count_ = 1;
}
}
public:
int change_count_ = 0;
};
int main() {
Example example;
printf("Pre: %d\n", example.change_count_);
example.change_count_ = 2147483647; // MAX_INT
printf("Mid: %d\n", example.change_count_);
example.Change();
printf("Pst: %d\n", example.change_count_);
return 0;
}
使用这些命令构建时:
gcc -fPIC -g3 -O1 -g -std=gnu++11 weird.cpp -o optimized
gcc weird.cpp -o normal
程序 normal
按预期执行,输出如下:
Pre: 0
Mid: 2147483647
Pst: 1
但是 optimized
给出了以下意想不到的行为:
Pre: 0
Mid: 2147483647
Pst: -2147483648
附加到调试器显示增量是在函数的最后完成的。 C++ 中是否未定义溢出行为?或者我应该用不同的方式处理这个问题吗?
这是我使用的 clang 版本:
tiny.local:~/scratch/weird_inc$ gcc -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 10.0.0 (clang-1000.10.44.4)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
我在 Ubuntu 中用 gcc 5.4.0
进行了测试,它给了我正确的答案。
有符号整数溢出 is undefined behavior in the current C++ standard。
编译器可以自由假设未定义的行为永远不会发生,并且不需要编译依赖于未定义行为的代码。
这意味着编译器可以安全地假设递增大于 0 的正值永远不会产生负值或 0。
您的编译器正在积极优化代码。编译器看到变量被初始化为正值,并递增。因此,编译器假定结果不能为负或 0,因此比较甚至不会被编译,因为它永远不可能为真。
我有一些我的优化器没有预料到的奇怪行为。基本上这是一个变量溢出的情况,我试图用来处理它的逻辑正在中断。
这是完整的程序 (weird.cpp
):
#include <stdio.h>
class Example {
public:
void Change() {
change_count_++;
// Check for overflow. If it does, set to 1 which is still valid
if(change_count_ <= 0) {
change_count_ = 1;
}
}
public:
int change_count_ = 0;
};
int main() {
Example example;
printf("Pre: %d\n", example.change_count_);
example.change_count_ = 2147483647; // MAX_INT
printf("Mid: %d\n", example.change_count_);
example.Change();
printf("Pst: %d\n", example.change_count_);
return 0;
}
使用这些命令构建时:
gcc -fPIC -g3 -O1 -g -std=gnu++11 weird.cpp -o optimized
gcc weird.cpp -o normal
程序 normal
按预期执行,输出如下:
Pre: 0
Mid: 2147483647
Pst: 1
但是 optimized
给出了以下意想不到的行为:
Pre: 0
Mid: 2147483647
Pst: -2147483648
附加到调试器显示增量是在函数的最后完成的。 C++ 中是否未定义溢出行为?或者我应该用不同的方式处理这个问题吗?
这是我使用的 clang 版本:
tiny.local:~/scratch/weird_inc$ gcc -v
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 10.0.0 (clang-1000.10.44.4)
Target: x86_64-apple-darwin17.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
我在 Ubuntu 中用 gcc 5.4.0
进行了测试,它给了我正确的答案。
有符号整数溢出 is undefined behavior in the current C++ standard。
编译器可以自由假设未定义的行为永远不会发生,并且不需要编译依赖于未定义行为的代码。
这意味着编译器可以安全地假设递增大于 0 的正值永远不会产生负值或 0。
您的编译器正在积极优化代码。编译器看到变量被初始化为正值,并递增。因此,编译器假定结果不能为负或 0,因此比较甚至不会被编译,因为它永远不可能为真。