不管你使用哪种方法调试代码,都需要有足够的耐性
方法一:在代码中加入打印语句--》在关键语句的前后(函数调用),关键变量
方法二:使用gdb调试(原理也是让程序分步执行,打印关键变量的值)
(1)使用gdb在编译程序的时候必须加上-g选项(将程序的调试信息添加到生成的可执行程序中)
gcc mytree.c -o mytree -g
(2)开始调试
gdb 程序的名字
(3)常用的gdb调试命令
不管你使用哪种调试方法:首先要做的事情是缩小错误的范围
一:打印代码内容
l 默认列举源码的前面10行
l 1,20 列举前面1到20行
二:设置断点(可以设置多个断点)
b 行号 程序等会运行到断点所在的行就停下来
info b 帮助你查看目前所有的断点信息
d 断点的序号 取消断点
三:单步执行程序
n
s
区别:遇到自定义的函数调用
n 一下子直接执行完,退出函数
s 进入函数代码中,一行行执行
n不会进入函数内部一行行去单步调试,s会
四:打印变量值
p 变量的名字
五:继续运行程序
c
六:运行程序
r //不带参数
r 参数 //带参数运行
如果以上无法确定错误来源,而且错误是段错误Segmentatin fault(就是你的程序访问了非法的内存,比如使用了野指针)
可以让 gdb 帮我们直接定位出现段错误的地方。
A) 使用 -g 编译待调试代码
B) 去掉系统对core文件的大小限制: ulimit -c unlimited
C) 重新让程序死一遍,产生一个core文件
D) 使用 gdb 来直接定位: gdb ./example core (注意:不是100%能解决问题,看运气)
2.3 如果发生的不是段错误,或者用以上办法,gdb无法直接定位段错误的位置,那就只能单步调试
gdb 可供使用的常用命令:
> list/l/l 10/l 2,30 (列出当前正在调试的代码)
> breakpoint/b 20 (在第20行设置了一个断点)
> b 20 if i>=100 (在第20行设置了一个条件断点)
> b somefunction (在函数somefunction设置了一个断点)
> run/r/r 123 abc (启动程序开始运行,可以带参)
> print i/p i (查看变量i当前的值)
> display i (持续跟踪变量 i 变化)
> backtrace full/bt full (查看当前栈内存的详细细节)
> whatis i (查看变量i的类型)
> next/n (单步执行:函数调用将会被当做一步)
> step/s (单步执行:将会进入函数调用内部)
> continue/c (继续执行代码,直到遇到下一个断点,或者程序退出)
> quit/q (退出调试器gdb)