C语言入门(21)——使用DBG对C语言进行调试
C语言入门(21)——使用DBG对C语言进行调试
程序中除了一目了然的Bug之外都需要一定的调试手段来分析到底错在哪。到目前为止我们的调试手段只有一种:根据程序执行时的出错现象假设错误原因,然后在代码中适当的位置插入printf,执行程序并分析打印结果,如果结果和预期的一样,就基本上证明了自己假设的错误原因,就可以动手修正Bug了,如果结果和预期的不一样,就根据结果做进一步的假设和分析。
我们介绍一种非常强大的调试工具gdb,可以完全操控程序的运行,并且随时可以查看程序中所有的内部状态,比如各变量的值、传给函数的参数、当前执行的语句位置等。调试的基本思想仍然“分析现象->假设错误原因->产生新的现象去验证假设”这样一个循环,根据现象如何假设错误原因,以及如何设计新的现象去验证假设,这都需要非常严密的分析和思考,如果因为手里有了强大的工具就滥用,而忽视了严谨的思维,往往会治标不治本地修正Bug,导致一个错误现象消失了但Bug仍然存在,甚至是把程序越改越错。
单步执行和跟踪函数调用
看下面的程序:
#include <stdio.h>int add_range(int low, int high)
{int i, sum = 0;for (i = low; i <= high; i++)sum = sum + i;return sum;
}int main(valoid)
{int result[100];result[0] = add_range(1, 10);result[1] = add_range(1, 100);printf("result[0]=%d\nresult[1]=%d\n", result[0], result[1]);return 0;
}
add_range函数从low加到high,在main函数中首先从1加到10,把结果保存下来,然后从1加到100,再把结果保存下来,最后打印出的两个结果是:
结果显然不正确,在小学我们就学了高斯小时候的故事,从1加到100应该是5050。下面通过gbd把错误找出来。
在编译时要加上-g选项,生成的目标文件才能用gdb进行调试:
(gdb) -g选项的作用是在目标文件中加入源代码的信息,比如目标文件中第几条机器指令对应源代码的第几行,但并不是把整个源文件嵌入到目标文件中,所以在调试时目标文件时必须保证gdb也能找到源文件。gdb提供一个类似shell的命令行环境,上面的(gdb)就是提示符,在这个提示符下输入help可以查看命令的类别:
可以进一步查看某一类别中有哪些命令,例如查看files类别下有哪些命令可以用:
现在试试用list命令从第一行开始列出源代码:
一次只列10行,如果要从11行开始继续列源代码可以输入
(gdb) list
也可以什么都不输直接敲回车,gdb提供了一个很方便的功能,在提示符下直接敲回车表示用适当的参数重复上一条命令。
gdb的很多常用命令有简写形式,例如list命令可以写成l,要列一个函数的源代码也可以用函数名做参数:
gcc的-g选项并不是把源代码嵌入到目标文件中的,在调试目标文件时也需要源文件。我们继续调试。首先用start命令开始执行程序:
这表示停在main函数中变量定义之后的第一条语句处等待我们发命令,gdb列出这条语句表示它还没执行,并且马上要执行。我们可以用next命令(简写为n)控制这些语句一条一条地执行:
用n命令依次执行两行赋值语句和一行打印语句,在执行打印语句时结果立刻打出来了,然后停在return语句之前等待我们发命令。虽然我们完全控制了程序的执行,但仍然看不出哪里错了,因为错误不在main函数而在add_range函数,现在用start命令重新来过,这次用step命令(简写为s)进入函数中去执行:
这次停在了函数中变量定义之后的第一条语句处。在函数中有几种查看状态的办法,backtrace命令(简写为bt)可以查看函数调用的栈帧:
可见当前的add_range函数是被main函数调用的,main传进来的参数是low=1,high=10。main函数的栈帧编号为1,add_range的栈帧编号为0。现在可以用info命令(简写为i)查看add_range局部变量的值:
用s或n往下走几步,然后用print命令(简写为p)打出变量sum的值:
根据上面两步的结果我们可以看到,变量sum没有做初始化,所以直接导致后面的运算结果错误。
这时候我们已经找到错误原因,可以退出gdb修改源代码了。
代码修改如下:
#include <stdio.h>int add_range(int low, int high)
{inti, sum = 0;for(i = low; i <= high; i++)sum= sum + i;returnsum;
}int main(void)
{intresult[100];result[0]= add_range(1, 10);result[1]= add_range(1, 100);printf("result[0]=%d\nresult[1]=%d\n",result[0], result[1]);return0;
}
修改完毕重新编译并运行:
发现结果正确了。
下面是常用的gdb指令:
backtrace(或bt) 查看各级函数调用及参数
finish 执行到当前函数返回,然后停下来等待命令
frame(或f) 帧编号 选择栈帧
info(或i) locals 查看当前栈帧局部变量的值
list(或l) 列出源代码,接着上次的位置往下列,每次列10行
list 行号 列出从第几行开始的源代码
list 函数名 列出某个函数的源代码
next(或n) 执行下一行语句
print(或p) 打印表达式的值,通过表达式可以修改变量的值或者调用函数
set var 修改变量的值
start 开始执行程序,停在main函数第一行语句前面等待命令
step(或s) 执行下一行语句,如果有函数调用则进入到函数中
C语言入门(21)——使用DBG对C语言进行调试相关推荐
- c语言入门自学ppt文库,《C语言入门基础》PPT课件.ppt
第3章C语言入门基础 在正式学习C语言之前首先要掌握C语言的基本知识 如数制 对象的命名即标识符 以及C语言中的数据类型等 通过本章的学习为以后几章打下基础 3 1标识符 在C语言中 程序的编写是运用 ...
- c语言入门自学免费app,C语言入门学习最新版下载-C语言入门学习app手机版v1.0.2 安卓版-腾飞网...
C语言入门学习app手机版是一款c语言编程自学软件,零基础也可以学习,里面有海量教学视频,针对c语言不同程度的讲解都囊括其中.随时随地学习编程都可以,不用担心自己没有基础.还支持在手机上敲代码编程哦. ...
- c语言入门经典18个程序,C语言入门经典
面向C语言初学者,详细且全面地讲解了C语言的各种知识,从基础知识到高级应用,由浅入深,循序渐进地引领读者掌握C语言中的各种编程技术,体会C语言的灵活与强大.同时,<C语言入门经典>着眼于应 ...
- lua语言入门学习(二)lua语言的特点及注意事项
lua语言入门学习 lua语言的特点及注意事项 文章目录 lua语言入门学习 lua语言的学习地址 一.lua语言特点 1.注释 2.全局变量和局部变量 3.lua数据类型 4.字符串类型 5.多变量 ...
- C语言二进制标识符,C语言入门基础大全,自学C语言必备知识!
C语言作为一门非常适合编程入门的语言,打好基础的重要性不言而喻.所以特此奉上这一篇干货,希望小伙伴们能从中受益. 一.C语言程序的结构认识 用一个简单的c程序例子,介绍c语言的基本构成.格式.以及良好 ...
- R语言入门教程知识 第一章 R语言
R语言 R是用于统计分析.绘图的语言和操作环境.R是属于GNU系统的一个自由.免费.源代码开放的软件,它是一个用于统计计算和统计制图的优秀工具. R语言特点 R作为一种统计分析软件,是集统计 ...
- c语言入门第6,c语言入门经典 第5版_c语言入门经典_c语言入门自学(6)
1.8.5 函数体 main()函数的一般结构如图l-2 所示: 函数体是在函数名称后面位于起始及结束两个大括号之间的代码块.它包含了定义函数功能的所有语句.这个例子的main()函数体非常简单,只有 ...
- c语言入门程序下载,简单实用——C语言入门程序练习
#include #include struct structstudent//创建结构体,表示学生信息 { int No;//学号 char Name[20];//姓名 int Age;//年龄 } ...
- 《c语言入门题目4》用c语言计算圆环的面积
前言:(内容仅供分享和参考) 输入圆环内半径和圆环外半径即可获得圆环面积,是不是很高级(雾) bigR和smallR实际上都可以用r和R表示,没必要输的那么标准,但说明还是要说明清楚的. ====== ...
- 大一C语言入门到底怎么学
大一C语言入门到底怎么学? 大一C语言入门按照下面路线来,以及把下面的100道C语言编程案例学会就入门啦- 入门篇 1.什么是计算机语言 2.C语言的程序的结构 3.运行C语言的步骤与方法 4.了解简 ...
最新文章
- python elseif用法_python学习笔记(一)
- Android在屏幕任意位置显示对话框
- web第五章 json
- 前端学习(1761):前端调试值之如何对站点下的资源进行全部搜索
- Android 8.0 学习(12)---init.rc语法及解析过程总结
- Node.js ES6 模块化的基本语法-按需导出与按需导入
- note 2 运算符和表达式
- [笔记分享] [Camera] msm8926 camera hal 流程小结
- 如何更换ppt模板内容不变_怎么修改固定的ppt模板中的字和图片
- Rsoft光波导软件基于七芯光纤波导耦合器模拟
- bootstrap-datepicker属性和方法
- 成功项目经理的能力提升
- Ubuntu 18.04 安装Wine 微信
- mysql快速复制数据库中所有表及数据至另一个库中
- JAVA图形面积与周长(抽象类)
- java写wss,JAVA模拟WebSocket客户端,支持wss ssl证书
- 仪器仪表的介绍及发展
- PAT乙级 1048. 数字加密(20)
- 配置基于区域策略的防火墙
- jquery日期控件jedate的学习
热门文章
- 三菱PLC学习SMOV指令
- 那些可多人协作编辑的在线文档工具
- 手机与软件兼容测试软件,如何使用Total Control手机软件兼容性测试?
- 王自如与老罗的辩论赛谁赢了?!
- 射频流盘与射频孪生——流盘技术应用(1)
- Linux上wget: 无法解析主机地址
- IntelliJ IDEA V2022.1版本亮点——改进框架与技术
- oracle实体视图日志,Oracle案例02——ORA-12034: SCOTT.USER_TABLE 上的实体化视图日志比上次刷新后的内容新...
- hexo+yilia主题添加评论
- 我写了个随机点名系统,非常好用~ 我给它取名叫做——随机点名系统