什么时候需要检查整数溢出
When do I have to check for integer overflow?
我一直在研究整数溢出,最后我创建了一个函数来检查整数溢出和下溢:
#include <exception>
#include <limits>
int safe_add(int a, int b) {
if (a > 0 && b > INT_MAX - a) {
throw std::exception("Integer overflow");
} else if (a < 0 && b < INT_MIN - a) {
throw std::exception("Integer underflow");
}
return a + b;
}
我担心可能出现的性能问题,所以我做了下一个基准测试:
#include <iostream>
#include <exception>
#include <limits>
#include <chrono>
#include <string>
int safe_add(int a, int b) {
if (a > 0 && b > INT_MAX - a) {
throw std::exception("Integer overflow");
} else if (a < 0 && b < INT_MIN - a) {
throw std::exception("Integer underflow");
}
return a + b;
}
void bench_add() {
for (int i = INT16_MIN; i < INT16_MAX; i++) {
for (int j = INT16_MIN; j < INT16_MAX; j++) {
volatile int x = i + j; //I make it volatile so the compiler doesn't optimize it out
}
}
}
void bench_safe_add() {
for (int i = INT16_MIN; i < INT16_MAX; i++) {
for (int j = INT16_MIN; j < INT16_MAX; j++) {
volatile int x = safe_add(i, j); //I make it volatile so the compiler doesn't optimize it out
}
}
}
void bench_safe_add_with_try() {
try {
for (int i = INT16_MIN; i < INT16_MAX; i++) {
for (int j = INT16_MIN; j < INT16_MAX; j++) {
volatile int x = safe_add(i, j); //I make it volatile so the compiler doesn't optimize it out
}
}
} catch (std::exception& e) {
std::cout << e.what() << std::endl;
}
}
void chrono(const std::string& name, void function(void)) {
using namespace std::chrono;
milliseconds start = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
function();
long long time = (duration_cast<milliseconds>(system_clock::now().time_since_epoch()) - start).count();
std::cout << name << ": " << time << "ms" << std::endl;
}
int main() {
chrono("Standard add", bench_add);
chrono("Safe add", bench_safe_add);
chrono("Safe add surrounded by try block", bench_safe_add_with_try);
system("PAUSE");
return 0;
}
在我的机器(i7-6700K@4GHZ 16gb RAM)中产生如下输出:
Standard add: 1341ms
Safe add: 13667ms
Safe add surrounded by try block: 13544ms
如果我先用try块调用函数,那么安全添加时间会下降很多。也许是为了分支预测?
关键是,safe_add似乎比简单的添加要慢得多,所以我应该什么时候检查整数溢出?或者何时NOT检查整数溢出?对每个用户输入都使用它是否很重要,或者程序应该崩溃吗?当领导数据库时,性能影响要大得多,因为它需要另一个查询?
谢谢你,佩德罗。
@nikitoz已经给出了我想要的答案:
永远不需要检查整数溢出。验证用户输入对于一些真实世界的检查,如果您需要,请使用long long类型期望大整数,使用特殊的类来处理非常大的整数如果你真的需要,什么尺寸都行(通常不是)。程序不会整数溢出导致崩溃
因此我将其标记为已回答
相关文章:
- 整数溢出,最大值为 pow(10,19)
- 模函数,避免C++整数溢出
- 优化正在杀死我在 clang 6 中的整数溢出检查
- 从双精度转换为整数的显式类型是否始终检查整数溢出?
- 运行时错误:有符号整数溢出:964632435 * 10 无法在类型 'int' 中表示
- 我很难理解这些关于检测整数溢出的评论
- 检测 32 位整数溢出
- 如何在没有整数溢出的情况下找到n%(k*k)
- C 中俄罗斯农民算法中的整数溢出
- 检查Android NDK COD中的整数溢出
- 对于特定情况的整数溢出似乎是由整数溢出引起的错误
- 如何修复整数溢出警告
- 整数溢出 C++ 即使使用“无符号长整型”也是如此
- 整数溢出是否会影响其他变量
- 为什么功能不给整数溢出
- 有符号整数溢出、内部函数和未定义的行为
- 整数溢出不会发生:它们从0重新启动
- 以下程序中最大 int 1000 000(在 int 范围内)的整数溢出
- 为什么Turbo C Wraparound每次签名的整数溢出,尽管签名的整数溢出是不确定的
- 编译器是否有可能检测整数溢出或其他数据类型溢出的可能性