程序调试

gdb是一个调试C和C++程序的功能强大的调试器,能在程序运行时观察程序的内部结构和内存使用情况,主要提供以下功能:

  1.  监视程序中变量的值变化;
  2. 设置断点,指定代码行上暂停执行;
  3. 单步执行代码;
  4. 分析崩溃程序产生的core文件;

在bash(大多数linux系统的默认shell)命令行下直接输入gdb,或指定调试程序:

gdb filename

注:在使用gcc编译时,加上-g选项,程序编译包含调试信息;

在软件开发中,一个很重要的步骤就是软件测试和排除错误。错误有时bug对程序没有多大影响,有时返回错误的结果,但严重的bug甚至会造成程序跑飞、系统死机。开发者找到错误并消灭它们,该行为称为"调试(debug)"

当bug出现时,仅仅去查看源码,很难找出问题所在,需要借助一些手段去找到该些bug,并消灭它们。程序调试常见的手段包括单步调试、硬件调试、打印信息、log文件。

单步调试:利用调试器进行单步调试(如IDE中的Jlink)适合新手,最大好处是直观,能够帮助找到问题。缺点是限制性大、速度慢。

硬件调试:利用产品的硬件(LED、蜂鸣器等)进行调试,该方法比较适合裸机程序。

打印信息:利用printf函数打印调试,比较常见,其好处是具有普遍性,几乎在所有的情况都能使用。

log文件:log文件(日志文件)是系统运行过程中在特定时候打印的一些调试信息。log文件记录了这些调试信息,以供后续追查问题。比较合适系统级或大型程序调试。

调试信息太少会导致找不到问题所在;调试信息太多会导致大量的无用信息淹没有用信息,有用信息无法被测试人员发现。

调试(DEGBUG)版本和发行(RELEASE)版本区别

DEBUG版本包含了调试信息输出的版本。在程序测试时发布的DEBUG版本,在程序运行是会打印调试信息的log文件,可以辅助测试人员判断程序的问题所在。坏处是输出调试信息占用了系统资源,拖慢了系统运行速度,因此DEBUG版本的性能低于RESEALE版本。RELEASE版本是最终发布版本,相较于DEBUG版本,去掉了所有的调试信息,所以程序的运行效率要更高

debug宏的使用方法

#ifdef DEBUG
#define debug(fmt,args...) printf(fmt,##args)
#define debugX(level,fmt,args...) if(DEBUG >=level) printf(fmt,##args)
#else
#define debug(fmt,args...)
#define debugX(level,fmt,args...)
#endif    /*DEBUG*/

看下u-boot 下common.h头文件,了解如何定义debug宏,使用debug会输出自定义的信息;若没有定义,则什么也不会输出,即不执行任何语句。

#define print_error(str) do{fprintf(stderr),"Oh God!/nFile:%s Line:%d Function:%s:/n",__FILE__,__LINE__,__func__);perror(str); return (EXIT_FAILURE);}while(0)

它不仅打印会导致出错的文件、行号、函数,还打印这个出错的原因EXIT_FAILURE在系统中定义为1。也可以是exit(1),等。注意__FILE__等式C语言中的预定义宏,即是由C语言自己定义的。这些宏有特殊含义,如__FILE__表示当前正在编译的.c文件的文件名。值得注意的是,在Linux中有一些约定的习惯,如表示判断的函数,返回非0表示成功,返回0表示失败表示操作性质的函数,返回0表示操作成功,返回非0表示操作失败。经典的strcmp函数,如果要比较的两个字符串相同,它是返回0的

gdb调试

GDB GNU 开源组织发布的一个强大的 UNIX 下调试程序工具。

一般来说,GDB具有以下四个方面功能

  1. 启动程序,可按照你自定义的要求随心所欲的运行程序;
  2. 可让调试程序在所指定的位置断点处停止;
  3. 当程序停止时,可检查此时你的程序中所发生的事情;
  4. 动态的改变程序的执行环境

gdb常用的命令

编译生成执行文件 :gcc -g have_lunch.c -0 have_lunch

调用调试器gdb,装载子程序:  gdb have_lunch

列出源码list

设置断点并调试,在源程序第11行处: break 11     

设置断点,在函数func()入口处:   break func()               

查看断点信息info break   

运行程序  并在断点处停住: run

单挑语句执行:next(step)               

继续运行程序:continue   

 打印遍历i的值:print i 

(gdb) display 要显示值的表达式

查看函数堆栈:bt 

(gdb) bt
#0  0x00007ffff7bce0a2 in wait () from /lib64/libpthread.so.0
#1  0x0000000000400b43 in main () at have_lunch.c:51
(gdb) finish                       推出函数
Run till exit from #0  0x00007ffff7bce0a2 in wait () from /lib64/libpthread.so.0
main () at have_lunch.c:50
50        for(i=0;i<5;i++)

 退出gdb:quit 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值