【发布时间】:2018-09-01 06:25:08
【问题描述】:
我有一些金融应用程序的定点实现。它基本上是一个包含在一个类中的整数,该类基于给定的小数位数N视为十进制数。该类是偏执狂并检查溢出,但是当我在发布模式下运行测试时,它们失败了,最后我创建了一个演示问题的最小示例:
#include <iostream>
#include <sstream>
template <typename T, typename U>
typename std::enable_if<std::is_convertible<U, std::string>::value, T>::type
FromString(U&& str)
{
std::stringstream ss;
ss << str;
T ret;
ss >> ret;
return ret;
}
int main()
{
int NewAccu=32;
int N=10;
using T = int64_t;
T l = 10;
T r = FromString<T>("1" + std::string(NewAccu - N, '0'));
if (l == 0 || r == 0) {
return 0;
}
T res = l * r;
std::cout << l << std::endl;
std::cout << r << std::endl;
std::cout << res << std::endl;
std::cout << (res / l) << std::endl;
std::cout << std::endl;
if ((res / l) != r) {
throw std::runtime_error(
"FixedPoint Multiplication Overflow while upscaling [:" + std::to_string(l) + ", " + std::to_string(r) + "]");
}
return 0;
}
Clang 6 会发生这种情况,我的版本是:
$ clang++ --version
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
这很有趣,因为它是一个令人印象深刻的优化,但这会破坏我的应用程序并阻止我检测溢出。我能够重现此问题in g++ here。它不会在那里抛出异常。
请注意,异常是在调试模式下抛出的,但不是在发布模式下。
【问题讨论】:
-
用
volatile怎么样? -
@curiousguy 这可能是一个可能的解决方案。我现在就试试。但这不是矫枉过正吗?它会破坏我程序中的所有优化!
-
volatile严格适用于一个变量,它不会抑制之前或之后的优化。不过,它确实打破了通过 volatile 变量的值传播。就像输出到本地套接字并读回相同的值(这样编译器可能不会知道是相同的)。所以这取决于你是想要价值传播还是简单的修复。 -
对于溢出捕获定点算术,考虑CNL。
标签: c++ c++11 optimization integer-overflow fixed-point