不应该执行中断时执行中断';T intmain(intargc,char*argv[]){ int i=0; 对于(i=0;i这个代码在编译编译器上编译不好,因为它是无效的C++(空main < /COD>)。
与VS 2010一起编译和执行(与VS 2008中的版本相同)。我在最后一行(右括号)放置了一个断点,并通过调试器查看变量I。此代码将i保留为0。为什么?不应该执行中断时执行中断';T intmain(intargc,char*argv[]){ int i=0; 对于(i=0;i这个代码在编译编译器上编译不好,因为它是无效的C++(空main < /COD>)。,c++,if-statement,for-loop,break,C++,If Statement,For Loop,Break,与VS 2010一起编译和执行(与VS 2008中的版本相同)。我在最后一行(右括号)放置了一个断点,并通过调试器查看变量I。此代码将i保留为0。为什么? int main(int argc, char *argv[]) { int i = 0; for (i = 0; i < 50; i++) if (false) break; } intmain(intargc,char*argv[]){ int i=0; 对于(i=0;i < P>这个代码在编译编译
int main(int argc, char *argv[]) {
int i = 0;
for (i = 0; i < 50; i++)
if (false) break;
}
intmain(intargc,char*argv[]){
int i=0;
对于(i=0;i<50;i++)
如果(假)中断;;
}
在此之后-请注意break之后的第二个分号-i如预期的那样为50
有人能解释一下这个奇怪的行为吗?< /P> < P>这个代码在编译编译器上编译不好,因为它是无效的C++(<代码>空main < /COD>)。 也就是说,
i
的结果值是不相关的:编译器可以做它想做的任何事情
原因是
i
从未在循环外读取(其本身可证明没有效果),也没有声明volatile
,因此编译器可以证明没有明显的副作用,无论使用objdump-d-S查看生成的汇编代码时,i的值是多少,我们都可以看到GDB跳过循环的可能原因:
int main(int argc, char *argv[]) {
int i = 0;
for (i = 0; i < 50; i++)
if (false) break;;
}
0000000000 400584:
int main()
{
400584:55%按需付费
400585:48 89 e5 mov%rsp,%rbp
挥发性int i;
对于(i=0;i<5;i++)
400588:c7 45 fc 00移动$0x0,-0x4(%rbp)
40058f:eb 09 jmp 40059a
400591:8b 45 fc mov-0x4(%rbp),%eax
400594:83 C001添加$0x1,%eax
400597:89 45 fc mov%eax,-0x4(%rbp)
40059a:8b 45 fc mov-0x4(%rbp),%eax
40059d:83 f8 04 cmp$0x4,%eax
4005a0:0f 9e c0设定值%al
4005a3:84 c0测试%al,%al
4005a5:75个jne 400591
4005a7:b8 00 mov$0x0,%eax
if(false)
打破
}
4005ac:c9/Q
4005ad:c3 retq
4005ae:90无
4005af:90无
即使在编译时关闭了优化(-O0
标记为g++),实际上也不会为循环体生成代码。这可能意味着GDB将把循环视为单个语句,并且不会正确地单步执行循环
我在MSVC10中使用了GCC版本4.4.5和GDB版本7.0.1。,这是可复制的。我检查了拆卸。这似乎是pdb文件生成中的一个问题。返回循环开头的跳转指令与下一个源代码行混合在一起,就是这样。
如果按step键转到下一行,它将从return语句返回for循环的开头,并按预期执行循环50次。
. 如何检查i
的值?是否启用了编译器优化?第二个示例中的额外分号是循环外的一个空语句,因此从编译器的角度来看,这意味着这两个循环完全相同。只需使用g++
检查各种可能的组合,请始终查看50
。当然,您没有发布完整的示例,所以我不能确定我的代码是否与您的相同。。。也许你用某种奇怪的方式打印出来……试着做一个完整的例子,其他人可以测试。请看,在for条件下(i<50),似乎正在读取“i”,但for循环正在优化,因为“i”在其他任何地方都不会被读取。@Nick是的,这就是我的意思。澄清…编辑了原始帖子并改变了主要方法。听起来似乎有道理。但在“真实代码”中,测试条件并不总是错误的,编译器也没有机会对其进行优化。尽管如此,for循环似乎总是在一个周期后退出,只是看起来它实际上中断了。尝试将for循环中的i=0
更改为i=-100
,即(i=-100;i<50;i++)
。在调试器中,i
很可能仍然为零。一种解决方法是在循环体周围放置大括号,右大括号放在自己的行上。返回到循环开头的代码将与右大括号关联。如果可以复制,可以通过connect.microsoft.com存档,以便在将来的版本中修复。
0000000000400584 <main>:
int main()
{
400584: 55 push %rbp
400585: 48 89 e5 mov %rsp,%rbp
volatile int i;
for (i = 0; i < 5; i++)
400588: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
40058f: eb 09 jmp 40059a <main+0x16>
400591: 8b 45 fc mov -0x4(%rbp),%eax
400594: 83 c0 01 add $0x1,%eax
400597: 89 45 fc mov %eax,-0x4(%rbp)
40059a: 8b 45 fc mov -0x4(%rbp),%eax
40059d: 83 f8 04 cmp $0x4,%eax
4005a0: 0f 9e c0 setle %al
4005a3: 84 c0 test %al,%al
4005a5: 75 ea jne 400591 <main+0xd>
4005a7: b8 00 00 00 00 mov $0x0,%eax
if (false)
break;
}
4005ac: c9 leaveq
4005ad: c3 retq
4005ae: 90 nop
4005af: 90 nop