【发布时间】:2018-06-26 00:58:34
【问题描述】:
前几天我将我的 Windows 构建环境从 MSVC2013 升级到 MSVC2017,你瞧,我的程序中的一个函数多年来一直运行良好(在 g++/clang 下仍然运行良好)突然开始给出不正确的结果使用 MSVC2017 编译。
我能够重新编写函数以再次给出正确的结果,但这种经历让我感到好奇——我的函数是否调用了未定义的行为(直到现在才恰好给出正确的结果),或者代码是否定义明确并且MSVC2017 出了问题?
下面是一个简单的程序,展示了我重写之前和之后的玩具版本。特别是,当使用值为 -32762 的参数调用时,如下所示的函数 maybe_invokes_undefined_behavior() 是否会调用未定义的行为?
#include <stdio.h>
enum {ciFirstToken = -32768};
// This function sometimes gives unexpected results under MSVC2017
void maybe_invokes_undefined_behavior(short token)
{
if (token >= 0) return;
token -= ciFirstToken; // does this invoke undefined behavior if (token==-32762) and (ciFirstToken==-32768)?
if (token == 6)
{
printf("Token is 6, as expected (unexpected behavior not reproduced)\n");
}
else
{
printf("Token should now be 6, but it's actually %i\n", (int) token); // under MSVC2017 this prints -65530 !?
}
}
// This function is rewritten to use int-math instead of short-math and always gives the expected result
void allgood(short token16)
{
if (token16 >= 0) return;
int token = token16;
token -= ciFirstToken;
if (token == 6)
{
printf("Token is 6, as expected (odd behavior not reproduced)\n");
}
else
{
printf("Token should now be 6, but it's actually %i\n", (int) token);
}
}
int main(int, char **)
{
maybe_invokes_undefined_behavior(-32762);
allgood(-32762);
return 0;
}
【问题讨论】:
-
你用的是哪个版本的VS2017?我无法重现 v15.7.3(x86 或 x64,使用 /Od 或 /Ox)的问题。
-
我正在使用 v15.7.3,IIRC。
-
看到人们无法重现该问题,因此发布确切的编译器版本和编译开关以进行重现会有所帮助
-
他们的关键问题当然是
-(-32768)简而言之,数学溢出了未定义的行为。 MSVC 错误似乎是它正在将上面的有效代码转换为另一种形式,并意外引入了该 UB。 -
您确实需要告诉我们您平台上
SHORT_MIN和SHORT_MAX的值,以便确定定义了什么和没有定义什么。没有这些信息,这个问题几乎没有意义。
标签: c++ language-lawyer undefined-behavior msvc14