GDB调试艺术:处理奔溃和隐藏逻辑bug

Posted tyler_download

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GDB调试艺术:处理奔溃和隐藏逻辑bug相关的知识,希望对你有一定的参考价值。

程序奔溃是一件令人头疼之事,最要命的是那种运行很久后莫名其妙奔溃的情形。GDB调试器对处理奔溃很有用,当程序运行在GDB的管控下时,如果出现奔溃,那么它会直接指出奔溃的代码行,这使得奔溃查找变得非常高效,例如上次出现的段错误,如果我们使用GDB再次运行,它会停留在奔溃的代码行:
在这里插入图片描述

也就是说y[k]=y[k-1]这行导致奔溃,对于数组访问行程的奔溃而言,通常情况下就是数组元素读取越界,显然导致该原因的只能是下标k的值出现问题,于是我们使用print语句确认一下涉及到的几个变量值:

print k

上面指令运行后在我的环境下打印出976,显然这个值已经远远超出了数组y的元素个数,因此应该是k值出错了,仔细审查就能发现,其实它是在for循环中k++这条语句有问题,其实它应该是k–,修改后程序可以正常运行,于是我们可以输入一系列测试用例再次检验程序正确性,我们使用测试案例如下:

./insert_sort  12 5 17 23 7 1

运行后得到结果为:1 5 7 12 0 0, 数值17以后的元素没有插入到数组中,因此我们再次对这个问题进行调试,由于是数值17有问题,因此在变量new_y等于17时,insert函数的执行可能会出问题,于是设置断点如下:

break insert if num_y == 17

然后执行run 12 5 17 23 7 1, GDB会在num_y等于17时停止,首先我们看看此时数组y内的排序情况,因此执行print y,可以看到5, 12 正确的插入了数组y,于是我们可以通过next单步调试来看看它如何处理数值17,根据多次next可以发现,在insert函数中for (j = 0; j < num_y; j++)循环运行几次后根本没有执行scoot_over函数,也就是说代码没有执行 y[j] = new_y;这条元素插入操作。从代码上看我们能发现问题,那就是循环里只判断new_y小于当前数组元素的情况,如果大于数组里面元素,那么什么操作都不进行,因此代码需要处理这种情形,于是代码修改如下:

 if (new_y < y[j]) {
            scoot_over(j);
            y[j] = new_y;
            return;
        }
        else {
            y[num_y] = new_y;
        }

改完之后再次运行结果就正常了。

以上是关于GDB调试艺术:处理奔溃和隐藏逻辑bug的主要内容,如果未能解决你的问题,请参考以下文章

《软件调试艺术》读后感三

GDB的调试艺术:热手篇

《软件调试艺术》读后感一

ros项目调试:ROS项目使用GDB调试

GDB调试汇编堆栈

OpenHarmony标准系统实践之GDB调试