为什么clang中的-O2或更大的优化会破坏这个代码
Why does -O2 or greater optimization in clang break this code?
我在网站上检查了类似的问题,但在这里找不到任何符合我的场景的问题。这是我试图运行的代码(需要C++14(:
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
class countdownTimer {
public:
using duration_t = chrono::high_resolution_clock::duration;
countdownTimer(duration_t duration) : duration{ duration }, paused{ true } {}
countdownTimer(const countdownTimer&) = default;
countdownTimer(countdownTimer&&) = default;
countdownTimer& operator=(countdownTimer&&) = default;
countdownTimer& operator=(const countdownTimer&) = default;
void start() noexcept {
if (started) return;
startTime = chrono::high_resolution_clock::now();
endTime = startTime + duration;
started = true;
paused = false;
}
void pause() noexcept {
if (paused || !started) return;
pauseBegin = chrono::high_resolution_clock::now();
paused = true;
}
void resume() noexcept {
if (!paused || !started) return;
auto pauseDuration = chrono::high_resolution_clock::now() - pauseBegin;
startTime += pauseDuration;
endTime += pauseDuration;
paused = false;
}
double remainingSeconds() const noexcept {
auto ret = double{ 0.0 };
if (!started) ret = chrono::duration_cast<chrono::duration<double>>(duration).count();
else if (paused) ret = chrono::duration_cast<chrono::duration<double>>(duration - (pauseBegin - startTime)).count();
else ret = chrono::duration_cast<chrono::duration<double>>(duration - (chrono::high_resolution_clock::now() - startTime)).count();
return (ret < 0.0) ? 0.0 : ret;
}
duration_t remainingTime() const noexcept {
auto ret = duration_t{ 0ms };
if (!started) ret = chrono::duration_cast<duration_t>(duration);
else if (paused) ret = chrono::duration_cast<duration_t>(duration - (pauseBegin - startTime));
else ret = chrono::duration_cast<duration_t>(duration - (chrono::high_resolution_clock::now() - startTime));
return (ret < 0ms) ? 0ms : ret;
}
bool isPaused() const noexcept { return paused; }
bool hasFinished() const noexcept { return remainingTime() == 0s; }
void reset() noexcept {
started = false;
paused = true;
}
private:
chrono::high_resolution_clock::time_point startTime;
chrono::high_resolution_clock::time_point endTime;
chrono::high_resolution_clock::time_point pauseBegin;
duration_t duration;
bool paused;
bool started;
};
int main() {
countdownTimer timer(10s);
timer.start();
while (!timer.hasFinished()) {
cout << timer.remainingSeconds() << endl;
this_thread::sleep_for(1s);
}
}
这是一个简单的倒计时类,我为我的一个项目写的。main()
中的客户端代码非常不言自明,它应该输出从10到0的倒计时,然后退出程序。在没有优化或-O
/-O1
的情况下,它确实做到了:
10
8.99495
7.98992
6.9849
5.97981
4.9748
3.96973
2.9687
1.9677
0.966752
Program ended with exit code: 0
但是,如果我将优化提高到>=-O2
,程序就会一直输出10,并且永远运行。倒计时根本不起作用,它卡在了起始值。
我在OS X上使用最新的Xcode。clang --version
说Apple LLVM version 7.3.0 (clang-703.0.31)
。
奇怪的是,我的代码不包含任何奇怪的自写循环、未定义的行为或类似的东西,它几乎只是标准的库调用,所以优化破坏了它,这很奇怪
有什么想法吗?
附言:我还没有在其他编译器上尝试过,但我即将尝试。我会用这些结果更新这个问题。
bool started
未初始化。如果您将其初始化为false
,它将与-O2
:一起工作
实例
您可以使用Undefined behavior cleanufacturer:找到类似这样的错误
$ g++ -std=c++14 -O2 -g -fsanitize=undefined -fno-omit-frame-pointer main.cpp && ./a.out
main.cpp:18:9: runtime error: load of value 106, which is not a valid value for type 'bool'
错误在您的构造函数中:
countdownTimer(duration_t duration)
: duration{ duration }, paused{ true } {}
您忘记初始化started
。当您调用start()
时,这会触发未定义的行为。
没有一个我可以方便访问的clang版本会诊断这个错误,但GCC版本5和6(在Linux上-我的Mac上不再有GCC(会:
$ g++ -O2 -Wall -Wextra -std=c++14 test.cc
test.cc: In function ‘int main()’:
test.cc:18:13: warning: ‘*((void*)& timer +33)’ is used uninitialized in this function [-Wuninitialized]
if (started) return;
^~~~~~~
test.cc:74:20: note: ‘*((void*)& timer +33)’ was declared here
countdownTimer timer(10s);
^~~~~
(我的Xcode副本似乎有点过时了,有Apple LLVM version 7.0.2 (clang-700.1.81)
;它不会改变程序在-O2
的行为。如果你打开警告,你的clang可能会诊断出这个错误。(
(我已经向GCC提交了一份关于诊断中IR官样文章的错误报告。(
- C和C 中的代码优化
- 使用清理代码优化多个出口点
- 在 c++ 中从 txt 文件中提取条目的代码优化问题
- 为什么传递值参数经常使编译器更容易进行代码优化
- 来自MATLAB的代码优化直方图C
- C - 代码优化
- 代码优化子集总和
- 在代码优化过程中,C++11编译器是否会在可能的情况下将局部变量转换为右值
- C++-筛选Atkin代码优化
- 协议缓冲区 GetRepeatedField (反射) 代码优化
- C++代码优化
- 编译和代码优化
- C++ ARM 设备上代码优化的提示
- 我是否应该将 const 用于局部变量以获得更好的代码优化
- 用于并行计算的C++代码优化示例
- gcc/C++:如果CPU负载很低,那么代码优化用处不大,这是真的
- 反转每个单词在一个句子中使用c++需要代码优化我的代码片段
- 是我的编译器将适当的代码优化为无用的崩溃代码
- Arduino代码优化的多路复用LED矩阵
- 在代码优化中使用new运算符是否值得?