Linux之GDB调试介绍与应用20170601
一、GDB调试命令
|
描述 |
backtrace(或bt) |
查看各级函数调用及参数 |
finish |
连续运行到当前函数返回为止,然后停下来等待命令 |
frame(或f) 帧编号 |
选择栈帧 |
info(或i) locals |
查看当前栈帧局部变量的值 |
list(或l) |
列出源代码,接着上次的位置往下列,每次列10行 |
list 行号 |
列出从第几行开始的源代码 |
list 函数名 |
列出某个函数的源代码 |
next(或n) |
执行下一行语句 |
print(或p) |
打印表达式的值,通过表达式可以修改变量的值或者调用函数 |
quit(或q) |
退出 |
set var |
修改变量的值 |
start |
开始执行程序,停在 |
step(或s) |
执行下一行语句,如果有函数调用则进入到函数中 |
比如还有几个命令如下
wath 观察一个变量
current 跳转到下个断点,或则跳转到观察点
quit 退出gdb调试
特别地,对于段错误的解决:
1.编译的时候加上-g选项
2.在ARM开发板上:
2.1.ulimit -c unlimited
2.2.执行应用程序:程序出错时会在当前目录下生成名为core的文件
3.在PC上
3.1. arm-linux-gdb App core文件所在目录/core
3.2.在gdb中输入:backtrace 就可以知道在哪里出错
注意:
1.如果输入bt没有结果,或者提示无法运行,一般是没有权限导致的,chmod 777 core即可
2.出现0x40000780 in ?? ()
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
and all your stack frames look like this:
0x40000780 in ?? ()
一般是找不到动态库的原因:
解决办法
首先输入info sharedlibrary 查询缺少的动态库
然后把动态库拷贝到PC端的当前目录
最后设置路径为当前目录 set solib-search-path .
或者使用其他方式设置
http://blog.chinaunix.net/uid-24922718-id-3489839.html
http://www.fayewilliams.com/2013/01/31/gdb-unable-to-find-dynamic-linker-breakpoint-function/
http://bbs.chinaunix.net/thread-3611739-1-1.html
//可能动态库要加上-g才行
安装GDB:
- sudo apt-get install gdb
二、分析例子
代码如下:
- #include <stdio.h>
- int add_range(int low, int high);
- int add (int a, int b);
- int add (int a, int b) {
- int result = a + b;
- return result;
- }
- int add_range(int low, int high)
- {
- int i = 0, sum = 0;
- for (i = low; i <= high; i++)
- sum = sum + i;
- return sum;
- }
- int main(void)
- {
- 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]);
- int a = 9, b = 10;
- int result1 = a + b;
- int result2 = a * b;
- printf("result1 = %d, result2 = %d", result1, result2);
- int result3 = add(result1, result2) ;
- printf("result3=%d", result3);
- if (result3 == 10) {
- printf("result3 = %d", result3);
- } else {
- printf("result != 10");
- }
- return 0;
- }
1.在编译时要加上-g选项,生成的可执行文件才能用gdb进行源码级调试:
命令如下:
- gcc -g main.c -o hello1
- gdb hello1
如下图
2.然后我们怎么查看源代码呢?命令如下
- list
然后我们还要看下面的代码可以怎么样操作,你可以 回车 或则 输入l 之后回车(因为list 简写 l)注意很多gdb命令都可以简写成首字母,或则输入 list 2 回车也可以
我们退出gdb命令如下
- quit
我们这里先不退出
3.我们先运行程序用下面命令
- start
如下图
4.我们用next命令执行下一条语句,next命令简写为n,输入下民命令
- n
5.我们也可是使用step命令进入函数内入跟踪,简写命令s,再输入命令n执行下一步,输入下面命令
- s
6.在函数中有几种查看状态的办法,backtrace
命令(简写为bt
)可以查看函数调用的栈帧:
可见当前的add_range
函数是被main
函数调用的,main
传进来的参数是low=1, high=100
。main
函数的栈帧编号为1,add_range
的栈帧编号为0。
7.现在可以用info命令(简写为i)查看函数局部变量的值:
i locals
add_range函数局部变量的值:
v:shapes="_x0000_i1032">
如果想查看main函数当前局部变量的值也可以做到,先用frame命令(简写为f)选择1号栈帧然后再查看局部变量:
(gdb) f 1
输入下面命令
- i locals
8.我们还可以用p打印出当前值
9.我们也可以修改sum的值
- set var sum = 0
v:shapes="_x0000_i1036">
10.比如我们不要运行这个函数了,要运行这个函数下面的程序,我们可以用finish
- finish
11.quit
退出命令
v:shapes="_x0000_i1038">
三、断点调试
举例分析:
hello2.c源文件如下
- #include<stdio.h>
- int main() {
- int a = 1, b = 2, c = 3;
- int i;
- printf("hello chenyu");
- for (i = 0 ; i < 100; i++) {
- ++a;
- if (i > 90) {
- ++b;
- } else {
- ++c;
- }
- }
- printf("a = %d, b = %d, c = %d", a, b, c);
- int cc = 0;
- for (cc; cc < 9; cc++) {
- printf("c %d", i);
- }
- return 0;
- }
比如我们在 ++b (第10行)这行和printf("c %d", i)(第18行)这两行打断点示例:
1、编译
---在编译时要加上-g选项,生成的可执行文件才能用gdb进行源码级调试
gcc -g hello2.c
2、gdb调试
- gdb hello2
3、显示代码行数命令如下
- list
list(或l) |
列出源代码,接着上次的位置往下列,每次列10行 |
list 行号 |
列出从第几行开始的源代码 |
list 函数名 |
列出某个函数的源代码 |
回车 往下查看
4 、然后输入打断点命令
1) 、源文件的某一行设置断点
- break 行号
2)、一个特定的函数设置断点
- break 函数名
3)、设置条件断点
- break 行号 if 条件
示例:
- break 10
- break 18
图片如下:
5 、 运行并且跳转到断点
1)、运行
- start
2) 、跳转到断点命令(countine 简写c)
- c
程序就到++b 这行来,上面2个步骤也可以用这个run (简写 r)命令代码
- r
我们这里代码会跳到这个断点里面来,我么就避免了手动循环这么多次,因为这个断点会打很多次,所以我们可以用c命令,还是会在这行,所以打断点一般不要打在循环里面,当这个代码执行完之后,我们再用c命令,就会打印18行的代码
6、看函数局部变量的值或单个变量的值可以用下面命令
- i locals
- p c
如果想查看其他函数当前局部变量的值也可以做到,先用frame命令(简写为f)选择其他函数的栈帧号(backtrace
命令(简写为bt
)获取)然后再查看局部变量
f 1
i locals
7、进入函数内部用下面命令
- s
8、单步调试往下执行用下面命令
- n
9、删除断点
- delete 行号
10、我们也可以用watch命令来观察变量,如果变量的值发生变化,程序就会停止
- watch b
11、退出gdb命令
- quit
四、如何保存断点
有时候运行时,上次打的断点没了,怎么保存呢?
1、查看断点信息并保存
- info b
2
、保存断点
- save breakpoint fig.dp
断点保存在fig.dp文件里面
3、调试时候读取保存断点文件
- gdb hello2 -x fig.dp
要记住加上参数 -x
然后再去查看是否有断点
- info b
可以看到是有2个断点的
原文:http://blog.csdn.net/u011068702/article/details/53925415
http://blog.csdn.net/u011068702/article/details/53931648
五、实例:
示例1:
book@book-desktop:/work/projects/test$ gcc -o
LinkListClearOprNoHeadNode -g LinkListClearOprNoHeadNode.c
book@book-desktop:/work/projects/test$ gcc -g -o
LinkListClearOprNoHeadNode LinkListClearOprNoHeadNode.c
book@book-desktop:/work/projects/test$ gdb
LinkListClearOprNoHeadNode
GNU gdb (GDB)
7.0-ubuntu
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and
redistribute it.
There is NO WARRANTY, to the extent permitted by
law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /work/projects/test/LinkListClearOprNoHeadNode...done.
(gdb) list
35
-Input :
36
-Output :
37
-Return :
38 * Modify Date Version Author Modification
39 *
-----------------------------------------------
40 *
2017/03/29 V1.0.0 Yu Weifeng Created
41
******************************************************************************/
42 int main(int argc,char **argv)
43 {
44 PT_LinkList ptLinkListHead=NULL;
(gdb)
45 T_LinkListElement
tLinkListElement;
46 tLinkListElement.cData=1;
47
InsertNodeToLinkList(&ptLinkListHead,1,&tLinkListElement);
48 tLinkListElement.cData=23;
49
InsertNodeToLinkList(&ptLinkListHead,2,&tLinkListElement);
50 tLinkListElement.cData=24;
51
InsertNodeToLinkList(&ptLinkListHead,3,&tLinkListElement);
52 tLinkListElement.cData=26;
53
InsertNodeToLinkList(&ptLinkListHead,4,&tLinkListElement);
54 tLinkListElement.cData=66;
(gdb)
55
InsertNodeToLinkList(&ptLinkListHead,5,&tLinkListElement);
56 tLinkListElement.cData=99;
57 InsertNodeToLinkList(&ptLinkListHead,6,&tLinkListElement);
58
59 printf("插入结果:");
60 TraverseLinkList(ptLinkListHead);
61
DeleteNodeFromLinkList(ptLinkListHead,6,&tLinkListElement);
62 DeleteNodeFromLinkList(ptLinkListHead,4,&tLinkListElement);
63
64 printf("删除结果:");
(gdb)
65 TraverseLinkList(ptLinkListHead);
66
67 printf("插入结果:");
68 tLinkListElement.cData=5;
69 InsertNodeToLinkList(&ptLinkListHead,3,&tLinkListElement);
70 TraverseLinkList(ptLinkListHead);
71 return 0;
72 }
73
/*****************************************************************************
74
-Fuction :
GetLinkListLength
(gdb) info b
No breakpoints or watchpoints.
(gdb) break 47
Breakpoint 1 at 0x80484ca: file
LinkListClearOprNoHeadNode.c, line 47.
(gdb) start
Temporary breakpoint 2 at 0x80484bd: file
LinkListClearOprNoHeadNode.c, line 44.
Starting program: /work/projects/test/LinkListClearOprNoHeadNode
Temporary breakpoint 2, main (argc=1, argv=0xbffff784)
at LinkListClearOprNoHeadNode.c:44
44
PT_LinkList ptLinkListHead=NULL;
(gdb) c
Continuing.
Breakpoint 1, main (argc=1, argv=0xbffff784) at LinkListClearOprNoHeadNode.c:47
47
InsertNodeToLinkList(&ptLinkListHead,1,&tLinkListElement);
(gdb) s
InsertNodeToLinkList (i_pptLinkListHead=0xbffff6c8,
i_dwPosition=1, i_ptElement=0xbffff6cf) at LinkListClearOprNoHeadNode.c:114
114 int ret=-1;
(gdb) i locals
ret = 134513528
ptLinkListNode = 0xbffff6a8
ptInsertListNode = 0x8049ff4
iLen = 2424820
(gdb) p iLen
$1 = 2424820
(gdb) n
115 T_LinkList
*ptLinkListNode=*i_pptLinkListHead;
(gdb)
116 T_LinkList *ptInsertListNode=NULL;
(gdb)
117 int iLen=0;
(gdb)
118
iLen=GetLinkListLength(ptLinkListNode);
示例2:
book@book-desktop:/work/projects/test$
gdb LinkListClearOprNoHeadNode
GNU gdb (GDB)
7.0-ubuntu
Copyright (C) 2009
Free Software Foundation, Inc.
License GPLv3+: GNU
GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software:
you are free to change and redistribute it.
There is NO WARRANTY,
to the extent permitted by law. Type
"show copying"
and "show
warranty" for details.
This GDB was
configured as "i486-linux-gnu".
For bug reporting
instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from
/work/projects/test/LinkListClearOprNoHeadNode...done.
(gdb) list
InsertNodeToLinkList
108 * Modify Date Version Author Modification
109 * -----------------------------------------------
110 * 2017/03/29 V1.0.0 Yu Weifeng Created
111
******************************************************************************/
112 static int InsertNodeToLinkList(T_LinkList
**i_pptLinkListHead,int i_dwPosition,T_LinkListElement *i_ptElement)
113 {
114 int ret=-1;
115 T_LinkList
*ptLinkListNode=*i_pptLinkListHead;
116 T_LinkList *ptInsertListNode=NULL;
117 int iLen=0;
(gdb)
118
iLen=GetLinkListLength(ptLinkListNode);
119
if(i_dwPosition<1||i_dwPosition-1>iLen)
120 {
121 ret=-1;
122
printf("InsertPositionErr,Len:%d,Pos:%d\r\n",iLen,i_dwPosition);
123 }
124 else
125 {
126
ptInsertListNode=(T_LinkList *)malloc(sizeof(T_LinkList));
127 if(NULL==ptInsertListNode)
(gdb)
128 {
129 printf("pInsertListNodeMallocErr\r\n");
130 ret=-1;
131 }
132 else
133 {
134
ptInsertListNode->ptNext=NULL;
135 memcpy(&ptInsertListNode->tData,i_ptElement,sizeof(T_LinkListElement));
136
if(NULL==*i_pptLinkListHead)
137 {
(gdb)
138
*i_pptLinkListHead=ptInsertListNode;
139 }
140 else
141 {
142
while(--i_dwPosition)
143 {
144
ptLinkListNode=ptLinkListNode->ptNext;
145 }
146
ptInsertListNode->ptNext=ptLinkListNode;
147 ptLinkListNode=ptInsertListNode;
(gdb) info b
No breakpoints or
watchpoints.
(gdb) break 144
Breakpoint 1 at
0x804873f: file LinkListClearOprNoHeadNode.c, line 144.
(gdb) start
Temporary breakpoint 2
at 0x80484bd: file LinkListClearOprNoHeadNode.c, line 44.
Starting program:
/work/projects/test/LinkListClearOprNoHeadNode
Temporary breakpoint
2, main (argc=1, argv=0xbffff784) at LinkListClearOprNoHeadNode.c:44
44 PT_LinkList ptLinkListHead=NULL;
(gdb) c
Continuing.
ListNull
Breakpoint 1,
InsertNodeToLinkList (i_pptLinkListHead=0xbffff6c8, i_dwPosition=1,
i_ptElement=0xbffff6cf) at LinkListClearOprNoHeadNode.c:144
144
ptLinkListNode=ptLinkListNode->ptNext;
(gdb) i locals
ret = -1
ptLinkListNode =
0x804b008
ptInsertListNode =
0x804b018
iLen = 1
Linux之GDB调试介绍与应用20170601的更多相关文章
- 一文入门Linux下gdb调试(二)
作者:良知犹存 转载授权以及围观:欢迎添加微信号:Conscience_Remains 总述 今天我们介绍一下core dump文件,Core dump叫做核心转储,它是进程运行时在突然崩溃的 ...
- Linux知识(5)----LINUX下GDB调试
命令 解释 示例 file 加载被调试的可执行程序文件.因为一般都在被调试程序所在目录下执行GDB,因而文本名不需要带路径. (gdb) file gdb-sample r c Run的简 ...
- Linux下GDB调试简单示例
这里介绍对文件first.c的基本GDB调试操作,只有部分命令,只是一个示例,运行环境为装有gcc编译器和gdb调试器的Linux环境,基本GDB调试命令如下表: 命令 ...
- Linux嵌入式GDB调试环境搭建
======================= 我的环境 ==========================PC 端: CPU:x86_64, 系统:Ubuntu,IP:172.16.2.212开发 ...
- Linux+eclipse+gdb调试postgresql源码
pg内核源码解析课上用的vs调试pg源码, VS用起来确实方便,但是配置调试环境着实有点麻烦.首先得装个windows系统,最好是xp,win7稍微麻烦点:最好使用vs05,08和10也可以,但是比0 ...
- 一文入门Linux下gdb调试(一)
作者:良知犹存 转载授权以及围观:欢迎添加微信号:Conscience_Remains 总述 在window下我们习惯了IDE的各种调试按钮,说实话确实挺方便的,但到了Linux下,没有那么多的IDE ...
- Linux下GDB调试
GDB 是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形成执行 序列,形成脚本.UNIX 下的软件全是命令行的,这给程序开发提供了极大的便利,命令行 软件的优势在于, 他们可以非常容 ...
- Linux下GDB调试C/C++
首先先编译程序并生成调试符号: gcc -g -c main.cpp gcc -o exefile main.o 以上的exefile为可执行程序的文件名 然后: gdb exefile 可以开始gd ...
- Linux学习----gdb调试(指针的指针)
昨天遇到一个很奇怪的问题,如下: 按照理论,最后*p的值应该是99,不知为什么是15了,所以今天记录用gdb调试的过程,并熟悉gdb的使用. (调试过程参考:http://www.cnblogs.co ...
随机推荐
- dubbo SpringContainer
dubbo SpringContainer Spring启动类容器 SPI service provider interfaces 服务提供借口 Singleton 单例 ThreadSafe 线程安 ...
- mariadb BINLOG_FORMAT = STATEMENT 异常
当在mariadb中插入数据是报 InnoDB is limited to row-logging 异常: java.sql.SQLException: Cannot execute statemen ...
- 20181113-7 Beta阶段第1周/共2周 Scrum立会报告+燃尽图 05
作业要求https://edu.cnblogs.com/campus/nenu/2018fall/homework/2387 版本控制https://git.coding.net/lglr2018/F ...
- OGNL动态实现result
OGNL就是struts.xml文件中的<result>通过get()方法,动态获取action类中的变量 <struts> <package name="de ...
- 智能客服 利用python运行java代码
因为需要在linux中用python来进行分析,顾需要利用python来运行java中语音转文字和文字转语音代码 在python中运行java代码需要利用jpype
- 对其中的一个特点将NABC的分析结果
一.题目要求 每一个组员针对其中的一个特点将NABC的分析结果发表博客上(截止日期4月8日晚24:00前). 二.分析结果 特点之一:通讯方便 <渴了么>这个安卓APP特点之一就是通讯方便 ...
- HDU 5428 The Factor 分解因式
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5428 The Factor Accepts: 101 Submissions: 811 Tim ...
- ASLR/DEP绕过技术概览
在经典的栈溢出模型中,通过覆盖函数的返回地址来达到控制程序执行流程(EIP寄存器),通常将返回地址覆盖为0x7FFA4512,这个地址是一条JMP ESP指令,在函数返回时就会跳转到这个地址去执行,也 ...
- 开发环境解决 kafka Failed to send messages after 3 tries
新建了一个kafka集群,在window下写了一个简单的producer做测试,结果遇到了消息发送失败的问题,代码如下: Properties props = new Properties(); pr ...
- 3dContactPointAnnotationTool开发日志(二八)
师姐说物体间不能有穿透,于是我试了下给物体加rigidbody和meshCollider 然后就报错: 说是用meshCollider要么去掉刚体要么就把刚体设置为iskinematic. ...