用gdb调试程序

GDB是牛人写的一个很牛的调试器,虽然是命令行的,但是功能强大,习惯了就会非常喜欢,就像vim那样。如果你还是傻傻的通过printf语句来调试程序,赶紧行动起来,GDB是你很好的选择。

 

所谓调试程序,无非就是一个确认的过程,代码是正确的?错误的?在这个过程中出现任何问题都很正常,==写成了=?使用了空指针?不管错误多么弱智,都不能证明程序员弱智,没有出过错误的程序员是那些从来不写代码的程序员。

 

GDB调试器提供的操作包括很多,运行程序(run/r),设置断点(break/b)和临时断点(tbreak/t),单步调试(next/n以及step/s),恢复执行(continue/c),,查看变量(print/p),还有很多高级功能,诸如设置观察点(watchpoint/w),设置条件(conditional),查看堆栈(backtrace/bt)。

 

设置断点

GDB提供了三种不同的断点类型:

breakpoint:在制定位置处停止执行,这个位置可能是某一条语句或者某个函数入口处。

watchpoint:当内存中某个指定位置的数据发生变化时停止执行。

catchpoint:当某个特定事件发生时停止执行,break if sth,如break main if argc > 1,则如果参数argc的值大于2时,断点被触发。

 

当触发指定断点时,程序会停止执行,此时断点所在的语句还未执行。调试器为所有的断点进行编号,从1开始递增,在你设置断点时,会输出这个断点对应的标号。如果你忘了断点和标号的对应关系,可以使用命令info breakpoints来查看。

设置断点

break(b) func_name:在函数func_name的入口处设置断点

break(b) file_name:func_name:在文件file_name的指定函数func_name处设置断点

break(b) line_number:在当前文件的指定行号line_number处设置断点

break(b) file_name:line_number:在指定文件file_name的指定行号line_number处设定断点

 

采用上面的方法设置的断点,除非你主动的删除,否则他会一直在程序运行时存在,有时可能指向让断点终止程序一次,这时候可以使用临时断点,这种断点在一次触发后即自动删除。其使用方法和前面的断点相同,只是命令改为tbreak(t)。

除此之外,还可以设置硬件断点(hbreak),正则断点(rbreak)等。

 

需要注意,有时候编译器的优化会导致断点不再期待的位置被触发。

 

删除/关闭断点

 

有时可能某些断点不再需要(bug已修复)或者暂时不再需要(如在大型程序中已经确定某些模块,此时你可以删掉某些断点或者关闭某些断点。

删除断点可以使用两个指令,delete和clear。delete使用创建断点时分配的数字作参数,而clear则采用和break指令同样的语法。

delete identifier:删除标号为identifier处的断点,可以有多个标号

delete :删除所有断点

clear:删除设置在下一指令处的断点,也就是现在触发的断点。

clear func_name:删除函数func_name的入口处的断点

clear file_name:func_name:删除文件file_name的指定函数func_name处的断点

clear line_number:删除当前文件的指定行号line_number处的断点

clear file_name:line_number:删除指定文件file_name的指定行号line_number处断点

 

关闭断点使用指令disable identifier,重新开启断点使用指令enable identifier,或者使用enable once identifier,开启断点一次。

 

 

观察断点信息

每个断点除了一个唯一的标号以外,还有很多的属性,如前面讲的开启/关闭状态等。使用命令info breakpoints可以查看断点状态,前面已经说过了。

 

继续调试

在触发某个断点之后,如果你想继续调试余下的代码,有三种不同的方式:

(1)继续执行,直到下一断点处或者程序退出。

相应的指令为continue

(2)执行下一条指令

相应的指令为next和step,两者的区别在于如果碰到函数调用,step会进入函数体,执行该函数内的第一条指令,而next则会将该函数调用当作一条指令执行。

(3)继续执行,直到当前指令所在的函数执行结束或者当前的循环体结束

相应的指令为finish和until,区别在于,使用finish从循环体中退出时,只会从当前层中退出。

 

命令序列

使用GDB可以在指定断点处,设置命令序列,一旦断点触发,就会执行这些指令,格式为

commands break_identifier

 

gdb commands

 

end

如果gdb指令序列以scilent开头,则GDB不会输出断点信息(如断点位置,标号等)。如果最后一条指令是continue,调试器会自动执行这些指令序列(多见于循环中),不用用户输入continue命令。你也可以使用define把指令序列定义成宏。

 

监视断点

监视断点可以帮助我们在某个表达式的值发生变化时中断程序。这里的表达式可以是程序中的某个变量,也可以是包含这些变量的表达式语句。注意,要考虑变量的生存域问题,这和你在函数外部无法调用函数内部的局部变量一样。一旦变量超出生存域,监视断点会自动删除。

相应的命令为wathc expression

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值