zoukankan      html  css  js  c++  java
  • VS2005的一个关于调试的bug

      一开始先给出一段简单的C代码:

      

    #include <stdio.h>


    int main()
    {
    int i = 0;
    for ( ;i < 3; i++)
    {
    int num = printf("hello\n");
    if (num != 0)
    {
    break;
    }
    }
    printf(
    "aha,bye!\n");
    return 0;
    }

      代码非常简单,for循环应该循环3次,但是这里为了更好的演示这个bug,在第一次执行循环内的printf()语句时,程序就会因满足if语句的条件而跳出循环,事实上for循环在这里只会执行一次,这显然不是什么bug。

      那么bug在哪里呢?用VS2005或更新的版本编译这段C代码,我们希望在开始执行for循环时程序能断下来供我们分析,所以在for( ; i < 3; i++)这一句处按F9下个断点,按F5开始调试,程序居然直接执行完退出了,断点根本就没断下来,到底发生了什么?我们反汇编看一下就清楚了,先注释掉我们的if语句,现在for循环可以成功的执行三次,还是下同样的断点,开始调试,成功断下来后,切换到cmd窗口看一下,是不是已经输出了一次hello了?很奇怪吧,然后切换到反汇编界面,可以看到如下图所示:

      vs2005_breakpoint_bug

      从上图可以看到我们下的断点看起来确实是断在了for循环内的第一条指令0x004113B7地址上,但是再仔细看一下,当给变量i赋初值0后,在0x004113B5指令处直接jmp跳了下去,先去比较变量i是否小于3,如果大于等于3那么就通过jge跳出循环,如果小于3那么就执行printf()函数,输出完毕之后才会在0x004113E0处的这条jmp指令跳回到我们的断点处,也就是说第一次for循环的执行完全绕过了我们下的断点,如果第一次执行循环时通过break或者goto或者return之类的语句跳出循环了呢?或者第一次循环就不成立,0x004113C4处jge时就跳跑了呢?那么我们的断点就完全成了摆设,根本什么都断不下来!也就是我在一开始给出的那个小程序。

      当然也不是所有的for循环都有这个小bug,只是当for循环条件的第一个语句为空时才会这样,如果你通常都是写for(i = 0; i < 3; i++)那么这个bug就不会影响到你了。

      这个小bug很有意思,只有在VS2005以上的IDE环境下才会出现,而且应该都是Debug生成时才会这样,我试了一下VC6就没有这个问题,因为VC6认为0x004113B5处的jmp指令位于循环内,所以刚好断下来了,如下图:

      VC6_breakpoint

      两者的区别就是VC6如果在第一次断下后直接按F5继续运行,那么将一直运行到结束不会再次遇到这个断点,而VS2005虽然第一次循环断不下来,如果断下来之后按F5继续运行,那么每循环一次都会断一次。相比而言,我觉得还是VC6的行为更容易被接受,我调试程序时如果需要每次循环都中断,一般习惯将断点下在for循环的左大括号处,也就是上图的0x00401040这个地址处,如果希望第一次进入循环时中断,以后不再中断,则在for(...)这条语句处下断点。

      我想这已经能算是VS2005下断点的一个bug了,因为用户完全有可能写出下面的代码:

      

    int i = 0;
    for ( ;i < 3; i++)
    {
    //do something
    if (condition)
    {
    //do something
    break;
    }
    }

      如果第一次循环执行时就满足condition条件,那么断点将会什么都断不下来,一直运行到程序退出,就像最开始给出的那个代码一样。

      即使程序不是刚好这么巧,第一次执行循环时就跳出了,那么VS2005命中我们的断点时,也已经是第二次了,就像上面的例子中已经输出了一次hello一样。

  • 相关阅读:
    三、 复杂对象类型的WebService
    Axis2.x WebService开发指南目录索引
    eclipse/MyEclipse 日期格式、注释日期格式、时区问题
    IE6、IE7、IE8的CSS、JS兼容
    一、CXF WebService准备工作
    十二、用Axis操作 Header头部信息
    六、 跨多个WebService管理Session
    jQuery autocomplete 自扩展插件、自动补全示例
    二、Axis2的简单WebService示例
    六、传递、返回复杂类型的对象
  • 原文地址:https://www.cnblogs.com/pianoid/p/2076729.html
Copyright © 2011-2022 走看看