Visual C ++认为有符号整数溢出未定义? [英] Does Visual C++ consider signed integer overflow undefined?
问题描述
最近有人注意到,在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屋!