程序奔溃是一件令人头疼之事,最要命的是那种运行很久后莫名其妙奔溃的情形。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;
}
改完之后再次运行结果就正常了。