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

本文介绍了通过GDB调试器处理C程序运行时崩溃的问题,特别是针对数组越界导致的段错误。通过设置断点和单步调试,找出代码中的逻辑错误,即在插入排序算法中未处理新元素大于现有数组元素的情况。修正后的代码增加了对这种情况的处理,从而解决了程序异常并确保了正确性。
摘要由CSDN通过智能技术生成

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值