Skip to content

Latest commit

 

History

History
98 lines (41 loc) · 3.77 KB

[snowming]-2021-8-15-【C基础】课时13:一个玄学问题的解决.md

File metadata and controls

98 lines (41 loc) · 3.77 KB

0x01 前言

圆满完成了人生中的第一个C项目,项目如下:

title

相当于模拟一个内存管理系统。写项目的过程中不断地调试、也遇到了很多问题,记录几个调过的 bug。

0x02 通过函数改变全局变量的值

问题代码及输出:

title

title

问题分析:

我把 piece_end 定义为一个全局变量。现在的问题是,只是在函数的作用域内改变了 piece_end 的值,但是我实际想实现的是:通过函数在整个程序的作用域内改变 piece_end 变量的值。

上面的代码中,我把 piece_end 作为形参传入、自然只能在函数作用域内改变此变量的值。

解决方案是不把 piece_end 作为形参,只是通过函数改变此变量的值。

改正后的代码及输出:

title

title

于是此问题得到了解决。

0x03 通过插入 printf debug 异常退出

另一个 bug 是:我老遇到「程序卡住了」的问题。

比如下图中,我输入了新的/将要修改为的字符串 ear,程序自动计算出其长度为3,然后程序就卡住了:

title

程序是这样写的:

title

遇到这种问题的时候,可以这样调试:

title

最简单的办法是:
在红圈的地方插入一些 printf 语句。 看看哪些语句执行了,哪些些没执行。然后在对相应的位置进行单步调试。这样不用关心代码逻辑 直接定位 bug 大致位置。
单步调试一般是看 watch、memory 窗口 看相应的变量是否正常。

可以从上图中看出,主要是在一些 for、while 循环的地方插入 printf 语句,查看程序运行流程是走了哪个分支。

通过这样的调试方法,我定位到了 bug 的位置是在下面的 for 循环中:

title

title

我这里比如num=3,b=4。运行了一次不是应该跳出来继续执行修改成功吗,但是就卡住了:

title

定位了 bug 的位置,继续单步调试:把numb添加到watch窗口观察变量的变化(或者直接 printf 打印里面变量的值、寻找是否有异常值)。

title

结果发现:piece_end 的值为异常值,所以 piece[piece_end] 访问了不该访问的位置,发生数组越界,造成异常才退出(a[10]数组最多能访问a[10]而不报错,默认最多可以访问最大下标+1的位置)。

piece_end 为什么会出现异常值呢?这就又回到了我上面说的那个问题:piece_end 本来是全局变量,但是我把它当作参数传入了。删掉此形参、仅仅通过在函数中直接使用此全局变量来改变此变量的值,即可解决这个问题。

总结一下:在程序中出现这种卡住了的情况(异常退出),大部分是因为其中的循环出现了问题,可能的原因有:

  1. 变量没有自增、无法跳出循环
  2. 数组越界、造成异常退出

等......