Visual Studio 2013 中可能存在的 C/C++ 编译器错误
Posted
技术标签:
【中文标题】Visual Studio 2013 中可能存在的 C/C++ 编译器错误【英文标题】:Possible C/C++ compiler bug in Visual Studio 2013 【发布时间】:2017-03-01 17:55:08 【问题描述】:以下 C 或 C++ 代码的输出应为“11,11,11” 但是使用 Visual Studio Professional 2013(版本 12.0.40629.00 更新 5)输出为“11,0,0”!这仅发生在发布版本中,并在关闭优化时消失。这是编译器错误吗?
#include <stdio.h>
int main(void)
int A[100] = 0 ;
int row = 0; // BUG disappears if we make this const or short or char...
int ncols = 3; // BUG disappears if we make this const or short or char...
for (int y = row; y <= row; ++y)
for (int x = 0; x < ncols; ++x)
const int index = y * ncols + x;
//A[index] = 11; // (no bug !)
*(A + index) = 11; // BUG!!!
//*(A + y*ncols+x) = 11; // (no bug !)
//*(A + (y*ncols+x)) = 11; // BUG!!!
for (int x = 0; x < ncols; ++x)
printf("%d,", A[x]);
return 0;
【问题讨论】:
无法在 MSVC 2015 中重现。这是显示问题的 Minimal, Complete, and Verifiable example 吗? 我无法使用 Visual C++ 2015 更新 3 重现声称的行为。 @WeatherVane 检查 VS 2013。 只是想说,在 clang 3.9.1 上通过 -O2 运行它(我知道,与问题无关,但我很好奇)会产生 pretty funny asm result。无论团队是谁进行循环分析都应该感到自豪 =) 在 VS15 和 VS13 上进行了测试,包括 cpp 和 c。每次输出都是预期的。您能否向我们提供编译器的确切版本号。生成的程序集也很有趣。 【参考方案1】:是的,它似乎是一个编译器错误。在 Win32 版本的代码中,编译器使用寄存器 esi
表示 y
并使用寄存器 edx
表示 x
。正如@Ajay Brahmakshatriya 在 cmets 中正确指出的那样,编译器似乎尝试交换循环(将外部与内部交换),但最终得到的代码不正确。最后一条条件跳转指令,它应该代表 [exchanged] 内部循环,由于某种原因,它也将控制转移到检查esi
的位置。该检查会提前结束迭代。
0018206B xor esi,esi ; This is `y`
0018206D xor edx,edx ; This is `x`
...
00182070 test esi,esi
00182072 jg main+5Ch (018209Ch) ; Exit from the outer cycle?
00182074 lea eax,[edx+esi*2] ; Recalculate the starting storage location
00182077 add eax,esi ; for the next cycle:
00182079 lea ecx,[A] ; eax = esi * 3 + edx
0018207F lea eax,[ecx+eax*4] ; eax = &A[eax]
...
00182082 mov ecx,1 ; It is not exactly clear to me what this is
00182087 sub ecx,esi ; supposed to do, but when `esi` is `0`, it
00182089 add esi,ecx ; leaves `ecx` as 1, which is correct
; number of iterations for outer cycle
...
00182090 mov dword ptr [eax],0Bh ; Storing the value
00182096 lea eax,[eax+0Ch] ; Updating the pointer for the next storage location
00182099 dec ecx
0018209A jne main+50h (0182090h) ; Outer cycle [exchanged]
0018209C inc edx
0018209D cmp edx,3
001820A0 jl main+30h (0182070h) ; Inner cycle [exchanged]: for some reason it
; jumps to `test esi,esi`, which is what
; suddenly terminates the iterations
【讨论】:
此外,它向 eax 添加 12 而不是 4 的事实表明常量评估认为 y 是 1 而不是 0。 对我来说,它似乎已经执行了循环交换。它是执行 3 次的外部循环。内部循环(y)正在正确执行一次。但是 y 只是取了错误的值。 我可以请您从 A 打印更多值吗?我怀疑它会打印 11,0,0,11,0,0,11,0,0。 @Ajay Brahmakshatriya:是的,它添加 12 的原因相同:它认为内部循环不应该迭代。所以它为外循环的下一次迭代做准备。这毫无意义。 不,我认为它确实意识到内部循环将执行一次。但它只是假设 y 的值错误。不是假设 0,而是假设 1。以上是关于Visual Studio 2013 中可能存在的 C/C++ 编译器错误的主要内容,如果未能解决你的问题,请参考以下文章
基本字符串操作存在问题 [c++, visual studio 2013]
为啥最小 MFC 项目在 Visual Studio 2013 上存在链接错误?
Visual Studio 2013将不显示Winforms,错误“项目中已存在对组件的引用'系统'
Visual Studio 2013 Reference Hell - 它一直在寻找任何不存在的旧版本的 DLL - 为啥?