我们发现一个奇怪的问题,在VS2015 Update3编译器中,代码会无明显原因地被省略掉一部分。
我们发现:
- 这个问题只出现在VS2015 Update3中(Help|About显示为14.0.25431.01 Update 3,cl.exe版本为19.00.24215.1)
- 这个问题在VS2015 Update2中没有出现(Help|About显示为14.0.25123.00 Update 2,cl.exe版本为19.00.23918)
- 这个问题只在开启优化(例如默认的Release配置)时出现
- 这个问题在x86和x64上都会出现
- 当将代码片段插入全新的“Win32 Console Application”中时(我是指,不需要任何高级命令行选项),才会出现此问题
我们成功将问题代码最小化到以下代码片段:
#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>
int _tmain(int, _TCHAR*[])
{
volatile int someVar = 1;
const int indexOffset = someVar ? 0 : 1; // Loop omitted
// const int indexOffset = !someVar; // Loop omitted
// const int indexOffset = 0; // Good
// const int indexOffset = 1; // Good
// const int indexOffset = someVar; // Good
// const int indexOffset = someVar + 1; // Good
for (int i = 1 - indexOffset; i < 2 - indexOffset; ++i)
{
printf("Test passed\n");
}
return 0;
}
对于标有“循环被省略”的那些代码行,编译器会省略整个循环体。为什么?据我所知,并没有涉及到未定义行为。
第一个“循环被省略”的反汇编代码:
int _tmain(int, _TCHAR*[])
{
01151010 push ebp
01151011 mov ebp,esp
01151013 push ecx
volatile int someVar = 1;
01151014 mov dword ptr [ebp-4],1
const int indexOffset = someVar ? 0 : 1; // Loop omitted
0115101B mov eax,dword ptr [someVar]
// const int indexOffset = !someVar; // Loop omitted
// const int indexOffset = 0; // Good
// const int indexOffset = 1; // Good
// const int indexOffset = someVar; // Good
// const int indexOffset = someVar + 1; // Good
for (int i = 1 - indexOffset; i < 2 - indexOffset; ++i)
{
printf("Test passed\n");
}
system("pause");
0115101E push offset string "pause" (011520F8h)
01151023 call dword ptr [__imp__system (0115205Ch)]
01151029 add esp,4
return 0;
0115102C xor eax,eax
}
0115102E mov esp,ebp
01151030 pop ebp
01151031 ret
测试项目:http://dropmefiles.com/S7mwT
在线尝试!
- 进入http://webcompiler.cloudapp.net/
- 将示例代码放到编辑器中
- 在“附加编译器标志”中添加
/O2
- 勾选“编译后运行可执行文件”
tchar.h
,windows.h
和cstdio
。这绝对是编译器的错误 - 它可以在MSVC x64 19.10.25019(VS15 RTM)和19.11.25325(VS15.3 Preview)上工作。你应该升级你的编译器 - MSVC 19.0已不再受支持。 - tambrecl /?
。 - PaulMcKenziecl.exe
)的版本,而不是IDE的版本。这种信息在未来更为重要,因为使用较新版本的VS的项目可以使用来自其他VS版本的编译器工具链。 - Michael Burr