zoukankan      html  css  js  c++  java
  • 一个小bug的总结

    最近遇到一个bug,就是安装完我们的软件后,只要用户转移了桌面文件夹后(该功能是软件提供),删除或者保存到桌面上的文件要刷新一下才能显示出来,注销系统之后,重新登录就可以了(但是重启不可以,重启后还是要注销一次);最后代码的改动很小,但是找到这段有问题的代码却用了一个星期的时间,下面说说解决这个bug,遇到的那些坑,算是记录也算是给自己以后工作的提醒吧。首先,由于程序是由很多个exe模块和dll模块组成的,他们之间的调用关系我也不清楚,所以每次测试都需要重新build,整个时间大概要十几分钟(c++,你懂得),我先用搜索的方法找到了转移桌面的代码的大致位置,略加分析后,我通过不断的MessageBox定位到了某个dll中出问题的函数init(),用同样的方法我继续跟踪,最后注意到这样一段代码上,(这里简化了很多细节)

    init()

    {

      get_disk_index()
      {
        static bool init;
        if (!init) {
        do_something1();// 我不断测试的地方
        do_something2();
        init = true;
      }
      ...
      int ret = read_disk();  // 这个才是真正的问题所在
      ...
    }
    我想:init是个静态变量,在程序运行之后,它被设置为true,之后do_something1和do_something2就不再被执行了,所以软件启动后,这里的操作只做了一次,这也很符合注销之后就不用再刷新的现象!接下来把init设为false,这次发现注销之后,仍然需要刷新,注释了do_something1和do_something2,等待上十几分钟,果然,桌面不再被刷新了;「太好了,终于找到了!」,我把do_something1和do_something2两个函数单独拿出来测试,奇怪的事情发生了,他们根本不会影响桌面刷新,其实这个时候,我的方向已经错了,可能是我调试代码的时候,改动了别的地方没有还原,但我还没有察觉,我盯着这两个函数用功了两天,一无所获(可能有人会说,那你为什么不打MessageBox,看看问题出在哪一行上呢?我当然试过,但是,这个模块是在服务中被调用的,根本就不会弹出窗口,服务直接就罢工了)。我一狠心,把所有的代码都更新了,决定重头再来,重写测试代码;既然不可以用MessageBox但不调试,那我把每次的数据都打印出来分析总行了吧,这样又搞了两三天,还是一头雾水;这时候领导来问我进行的怎么样了,我只能说:「大概知道问题在哪里,不过调试不出来。」领导人很好并没催我,只是提醒了下我说:「你是不是没找对地方?」。当时我是真的很郁闷,领导走好,我点了下那个感叹号(用过vc6的同学都懂得),弹出来一个对话框,让我选择可执行程序。对啊!?我为什么不写个测试程序去掉用dll,这样不就可以用MessageBox单步调试了吗?而且测试的时间也会缩短很多啊!说干就干,测试程序写好了,添加lib,添加头文件,把dll放到当前目录,编译...,咦?缺少一 个头文件,拷贝过来,嗯?还缺少一个?再拷贝,啊?还缺少一个?再来!啊啊啊啊...缺少无数个头文件,我大喊一声,「天要亡我啊!」只能求助谷歌君。谷歌君告诉我,用LoadLibrary和GetProcAddress函数啊,ok,搞定!结果GetProcAddress一直返回NULL,奇怪,命名有这个函数啊,怎么获取不到呢?原来这个是C++代码,C++的编译器会做name mangling,使用dumpbin工具,查看dll的导出函数,找到对应的函数名,终于可以开始调试了,问题也很容易的解决了,而且真正出问题的代码是用注释标出来的地方(其实我很早就怀疑我测得地方不对,但就是太偏执一直不肯测那里);具体原因是因为DeviceIoControl(...,FSCTL_LOCK_VOLUME,...)的时候,函数调用失败导致了桌面不能刷新(调用了对应的DeviceIoControl(..,FSCTL_UNLOCK_VOLUME));我看了下代码,这个地方完全不需要调用这个函数,是之前的程序员为了省事,直接从另外一处复制过来的。

    总结:
    1.错误的方向,再怎么努力也是零;失败的时候,不能过于偏执,不要总纠结于自己的能力,有时候抬起头来看看大的方向,或许稍微努力就成功了。

    2.磨刀不误砍柴工;道理很多人懂,但是真正做的时候很容易被忽略;接到问题,马上开始动手,往往是最笨也是最低效的办法。与其花死力气去硬碰硬,不如多用点「巧劲」,多想想有没有更好的方法,这样才能「四两拨千斤」。

    3.工具很重要;公司代码管理用的cvs,diff代码的功能实在是太不直观了,一来影响工作的效率,二来改错了代码也很难发现。

    4.不负责任的复制粘贴很要人命;千万不要打着代码复用的旗号直接的复制粘贴,不仅害人而且害己。

  • 相关阅读:
    Javascript操作DOM常用API总结
    实用技巧之Visio绘制流程框图
    实用技巧之Visio绘图
    回复《竞赛部的一封信》
    学习之路
    《软件工程》上课精华分享
    《编译原理》上课笔记2
    sql server2008 远程过程调用失败
    《编译原理》上课笔记1
    python的第五天(复习数据类型)
  • 原文地址:https://www.cnblogs.com/joyzhuang/p/3625857.html
Copyright © 2011-2022 走看看