标签: integer-overflow

用于安全整数转换的C++模板

我正在尝试编写一个C++模板函数,它将在不同整数类型之间的转换中抛出整数溢出的运行时异常,具有不同的宽度,以及可能的有符号/无符号不匹配.出于这些目的,我不关心从浮点类型转换为整数类型,也不关心其他对象到对象的转换.我想这样做而不必写很多特殊的案例代码.这就是我目前拥有的:

template< typename T, typename R > void safe_cast( const T& source, R& result )
{
    // get the maximum safe value of type R
    R rMax = (R) ~0;
    if ( rMax < 0 ) // R is a signed type
    {
        // assume that we're on an 8-bit twos-compliment machine
        rMax = ~( 0x80 << ( ( sizeof( R ) - 1 ) * 8 ) );
    }

    if ( ( source & rMax  ) != source ) …
Run Code Online (Sandbox Code Playgroud)

c++ templates casting integer-overflow

11
推荐指数
4
解决办法
6585
查看次数

没有有用和可靠的方法来检测C/C++中的整数溢出?

不,这不是如何检测整数溢出的重复.问题是一样的,但问题是不同的.


gcc编译器可以优化掉溢出检查(使用-O2),例如:

int a, b;
b = abs(a);                     // will overflow if a = 0x80000000
if (b < 0) printf("overflow");  // optimized away
Run Code Online (Sandbox Code Playgroud)

gcc人认为这不是一个错误.根据C标准,溢出是未定义的行为,它允许编译器执行任何操作.显然,任何事情都包括假设溢出永远不会发生.不幸的是,这允许编译器优化掉溢出检查.

最近的CERT文件中描述了检查溢出的安全方法.本文建议在添加两个整数之前执行类似的操作:

if ( ((si1^si2) | (((si1^(~(si1^si2) & INT_MIN)) + si2)^si2)) >= 0) { 
  /* handle error condition */
} else {
  sum = si1 + si2;
}
Run Code Online (Sandbox Code Playgroud)

显然,当你想确保结果有效时,你必须在一系列计算中的每个+, - ,*,/和其他操作之前做这样的事情.例如,如果要确保数组索引不受限制.这太麻烦了,几乎没有人这样做.至少我从未见过一个系统地执行此操作的C/C++程序.

现在,这是一个根本问题:

  • 在访问阵列之前检查数组索引很有用,但不可靠.

  • 使用CERT方法检查一系列计算中的每个操作都是可靠但无用的.

  • 结论:在C/C++中没有有用且可靠的方法来检查溢出!

我拒绝相信这是在编写标准时的意图.

我知道有一些命令行选项可以解决问题,但这并没有改变我们对标准或其当前解释存在根本问题的事实.

现在我的问题是:gcc的人服用的"未定义行为"的解释时,它允许他们优化掉溢出检查,否则过犹不及是C/C++标准坏了吗?

补充说明: 对不起,您可能误解了我的问题.我不是问如何解决这个问题 - 这已经在其他地方得到了回答.我在问一个关于C标准的更基本的问题.如果没有有用且可靠的检查溢出的方法,那么语言本身就是可疑的.例如,如果我使用边界检查创建一个安全的数组类,那么我应该是安全的,但是如果边界检查可以被优化掉,我就不会这样做.

如果标准允许这样做,则标准需要修订或标准需求修订的解释.

补充说明2: 这里的人似乎不愿意讨论"未定义行为"的可疑概念.C99标准列出了191种不同的未定义行为( …

c c++ overflow integer-overflow gcc4

11
推荐指数
1
解决办法
2434
查看次数

如何安全地在unsigned int和int之间进行static_cast?

我有一个8个字符string代表一个十六进制数字,我需要将其转换为int.这种转换必须保留字符串"80000000"和更高的位模式,即这些数字应该是负数.不幸的是,天真的解决方案:

int hex_str_to_int(const string hexStr)
{    
    stringstream strm;
    strm << hex << hexStr;
    unsigned int val = 0;
    strm >> val;
    return static_cast<int>(val);
}
Run Code Online (Sandbox Code Playgroud)

如果val > MAX_INT(返回值为0),则对我的编译器不起作用.更改val的类型int也会导致较大的数字为0.我在SO上尝试了几种不同的解决方案,但尚未成功.

这就是我所知道的:

  • 我在OpenVMS上使用HP的C++编译器(我相信,使用安腾处理器).
  • sizeof(int) 我的代码将在每个架构上运行至少4个.
  • 从数字> INT_MAX到int的转换是实现定义的.在我的机器,它通常会导致0但有趣的是铸造longint的结果INT_MAX,当值过大.

这是非常难以正确地做到,或者至少它已经适合我.有谁知道这个便携式解决方案?

更新:

更改static_castreinterpret_cast导致编译器错误.评论促使我尝试C风格的演员:return (int)val在上面的代码中,它工作. 在这台机器上. 在其他架构上,这仍然是安全的吗?

c++ casting integer-overflow openvms

11
推荐指数
3
解决办法
2万
查看次数

在发生溢出的情况下,stdint.h中定义的C99签名整数类型是否表现出良好定义的行为?

对于C(short,int,long等)中的"标准"有符号整数类型的所有操作,如果它们产生超出[TYPE_MIN,TYPE_MAX]间隔的结果(其中TYPE_MIN,TYPE_MAX是最小值和最大整数值),则表现出未定义的行为可以通过特定整数类型存储的.

但是,根据C99标准,所有intN_t类型都需要具有二进制补码表示:

7.8.11.1精确宽度整数类型
1. typedef名称intN_t指定有符号整数类型,其宽度为N,无填充位和二进制补码表示.因此,int8_t表示具有正好8位宽度的有符号整数类型.

这是否意味着intN_tC99 中的类型在整数溢出的情况下表现出良好定义的行为?例如,这段代码定义明确吗?

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

int main(void)
{
    printf("Minimum 32-bit representable number: %" PRId32 "\n", INT32_MAX + 1);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

c standards integer-overflow c99

11
推荐指数
1
解决办法
641
查看次数

Clojure - 用大数字计算

我想!1000在clojure中计算,如何在不获得整数溢出异常的情况下执行此操作?

我的阶乘代码现在是:(reduce * (range 1 1001)).

clojure overflow integer-overflow

11
推荐指数
2
解决办法
2684
查看次数

是否可以使用C++访问CPU中的溢出标志寄存器?

在执行数学运算之后,比如乘以两个整数,是否可以使用C++访问CPU中的溢出标志寄存器?如果没有其他快速方法来检查溢出?

c++ assembly flags integer-overflow

11
推荐指数
2
解决办法
6086
查看次数

通常大数字变为负数

自从我开始使用eclipse作为项目euler以来,我注意到大数字有时会变成看似随机的负数.我想这与传递类型的boudry有关.

如果你能向我解释这些负数是如何产生的,以及它背后的逻辑是什么,我将很高兴.另外,我怎样才能避免它们(最好不要使用BigInteger类).丹科!=)

java integer-overflow biginteger

11
推荐指数
2
解决办法
1万
查看次数

乘以整数并分配给Long时溢出

如果我在立即窗口中键入以下内容,则会出现运行时错误"6":溢出.

MsgBox 24 * 60 * 60
Run Code Online (Sandbox Code Playgroud)

为什么是这样?

这也失败了:

Dim giveTime  As Long 
giveTime  = 24 * 60 * 60
Run Code Online (Sandbox Code Playgroud)

为什么是这样?giveTime声明为Long类型,因此24×60×60 = 86400应该适合.

vba integer-overflow

11
推荐指数
2
解决办法
7093
查看次数

整数除法溢出

问题

我一直在考虑整数(类型int)溢出,并且我发现分裂可能溢出.

示例:在我当前的平台上,我有

INT_MIN == -INT_MAX - 1
Run Code Online (Sandbox Code Playgroud)

因此

INT_MIN < -INT_MAX
Run Code Online (Sandbox Code Playgroud)

因此

INT_MIN / -1 > -INT_MAX / -1
Run Code Online (Sandbox Code Playgroud)

因此

INT_MIN / -1 > INT_MAX.
Run Code Online (Sandbox Code Playgroud)

因此,除法(INT_MIN/-1)确实溢出.


问题

所以,我有两个问题:

  1. 可以编写什么(跨平台)C代码以防止除法溢出(对于类型(带符号)int)?

  2. 什么保证(在C或C++标准中)可能有助于设计代码?


例如,如果标准保证我们有

INT_MIN == -INT_MAX - 1
Run Code Online (Sandbox Code Playgroud)

要么

INT_MIN == -INT_MAX,
Run Code Online (Sandbox Code Playgroud)

然后出现以下代码以防止溢出.

#include <limits.h>

/*
      Try to divide integer op1 by op2.
      Return
        0 (success) or
        1 (possibly overflow prevented).
      In case of success, write the quotient to res.
*/

int safe_int_div(int * res, int op1, int op2) { …
Run Code Online (Sandbox Code Playgroud)

c c++ standards cross-platform integer-overflow

11
推荐指数
1
解决办法
3980
查看次数

如何在启用溢出检查的情况下编译和运行优化的Rust程序

我正在编写一个计算量很大的程序,在调试模式下运行起来非常慢.

我的程序也受到整数溢出的困扰,因为我正在从u8数组中读取数据并u8通过类型推断将扩展类型扩展到意外的位置,而Rust更喜欢溢出而不是将整数提升为更大的类型.

在发布模式下构建会禁用溢出检查:

cargo run --release
Run Code Online (Sandbox Code Playgroud)

如何通过优化运行时溢出检查来构建Rust可执行文件?

integer-overflow compiler-optimization rust

11
推荐指数
1
解决办法
5522
查看次数