Visual C ++认为有符号整数溢出未定义? [英] Does Visual C++ consider signed integer overflow undefined?

查看:194
本文介绍了Visual C ++认为有符号整数溢出未定义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


最近有人注意到,在C和C ++中,有符号整数溢出是正式未定义的。然而,给定的实现可以选择定义它;在C ++中,实现可以将 std :: numeric_limits< signed T> :: is_modulo 设置为 true 整数溢出对于该类型是明确定义的,并且像无符号整数那样进行换行。

It's gotten a lot of attention lately that signed integer overflow is officially undefined in C and C++. However, a given implementation may choose to define it; in C++, an implementation may set std::numeric_limits<signed T>::is_modulo to true to indicate that signed integer overflow is well-defined for that type, and wraps like unsigned integers do.

Visual C ++集 std :: numeric_limits< signed int> ;: :is_modulo true 。这几乎不是一个可靠的指标,因为GCC多年来设置为true,并且未定义有符号溢出。我从来没有遇到过一个情况,Visual C ++的优化器做了任何事情,但给循环行为的有符号整数 - 直到本周早些。

Visual C++ sets std::numeric_limits<signed int>::is_modulo to true. This has hardly been a reliable indicator, since GCC set this to true for years and has undefined signed overflow. I have never encountered a case in which Visual C++'s optimizer has done anything but give wraparound behavior to signed integers - until earlier this week.

我发现了一种情况,其中优化器发出x86-64汇编代码,如果将 INT_MAX 的值传递给特定函数,则该汇编代码执行不正确。我不能告诉它是否是一个错误,因为Visual C ++似乎没有说明是否有符号整数溢出被认为定义。所以我想知道,是否应该在Visual C ++中定义?

I found a case in which the optimizer emitted x86-64 assembly code that acted improperly if the value of exactly INT_MAX was passed to a particular function. I can't tell whether it's a bug, because Visual C++ doesn't seem to state whether signed integer overflow is considered defined. So I'm wondering, is it supposed to be defined in Visual C++?

编辑:我在Visual C ++ 2013 Update 2中阅读一个讨厌的错误时发现了在更新1中,如果启用优化,以下循环会生成错误的机器代码:

I found this when reading about a nasty bug in Visual C++ 2013 Update 2 that wasn't in Update 1, where the following loop generates bad machine code if optimizations are enabled:

void func (int *b, int n)
{
  for (int i = 0; i < n; i++)
    b[i * (n + 1)] = 1;
}

更新2个错误导致重复行的代码生成, b [i] = 1; ,这显然是错误的。它变成 rep stosd

That Update 2 bug results in the repeated line having its code generated as if it were b[i] = 1;, which is clearly wrong. It turned into rep stosd.

真正有趣的是, / em> version,Update 1.它生成的代码没有正确处理 n 完全等于 INT_MAX 。具体来说,如果 n INT_MAX ,乘法就好像 n long long 而不是 int - 换句话说,添加 n + 1

What was really interesting was that there was weirdness in the previous version, Update 1. It generated code that didn't properly handle the case that n exactly equaled INT_MAX. Specifically, if n were INT_MAX, the multiplication would act as if n were long long instead of int - in other words, the addition n + 1 would not cause the result to become INT_MIN as it should.

这是一个非常简单的方法,这个方法可以使用 INT_MIN 更新1中的汇编代码:

This was the assembly code in Update 1:

    movsxd  rax, edx          ; RDX = 0x000000007FFFFFFF; RAX = 0x000000007FFFFFFF.
    test    edx, edx
    jle     short locret_76   ; Branch not taken, because EDX is nonnegative.
    lea     rdx, ds:4[rax*4]  ; RDX = RAX * 4 + 4; RDX becomes 0x0000000200000000.
    nop                       ; But it's wrong. RDX should now be 0xFFFFFFFE00000000.
loc_68:
    mov     dword ptr [rcx], 1
    add     rcx, rdx
    dec     rax
    jnz     short loc_68
locret_76:
    retn

问题是我不知道这是否是一个编译器错误 - 在GCC和Clang,这不会是一个编译器错误,因为那些编译器认为带符号的整数溢出/下溢是未定义的。这是Visual C ++中的一个错误取决于Visual C ++是否认为有符号整数溢出/下溢是未定义的。

The issue is that I don't know whether this is a compiler bug - in GCC and Clang, this wouldn't be a compiler bug, because those compilers consider signed integer overflow/underflow to be undefined. Whether this is a bug in Visual C++ depends on whether Visual C++ considers signed integer overflow/underflow to be undefined.

除此之外,

推荐答案

您的示例可能有未定义的行为 n == INT_MAX ,但不仅仅是因为有符号整数溢出未定义(它可能不在Microsoft编译器上)。相反,你可能调用未定义的超越指针算术。

Your example probably does have undefined behavior for n == INT_MAX, but not just because of signed integer overflow being undefined (which it may not be on the Microsoft compiler). Rather, you are probably invoking undefined out-of-bounds pointer arithmetic.

这篇关于Visual C ++认为有符号整数溢出未定义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆