1.Gdb的基本调试

示例代码

//e.c
#include <stdio.h>
void debug(char *str)
{
printf("debug info :%s\n",str );
} int main(int argc,char *argv[]){
int i,j;
j=0;
for(i=0;i<10;i++){
j+=5;
printf("now a=%d\n", j);
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

gcc -g -o e e.c
调试gdb e
或者输入gdb
然后 file e

1. list 命令用法

list命令显示多行源代码,从上次的位置开始显示,默认情况下,一次显示10行,第一次使用时,从代码其实位置显示。

list n显示已第n行未中心的10行代码
list functionname显示以functionname的函数为中心的10行代码
  • 1
  • 2

2. 断点命令break
break location:在location位置设置断点,改位置可以为某一行,某函数名或者其它结构的地址。gdb会在执行该位置的代码之前停下来.

使用delete breakpoints 断点号 删除断点
这里的断点号表示的是第几个断点,刚才执行break 10返回
reakpoint 1 at 0x40050a: file e.c, line 10.
中的1表示该断点的标号,因此使用 delete breakpoints 1表示删除第10行所定义的断点 clear n表示清除第n行的断点,因此clear 10等同于delete breakpoints 1
disable/enable n表示使得编号为n的断点暂时失效或有效
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

可使用info查看断点相关的信息
info breakpoints

c(continue),继续程序运行直到下一个断点

3.display命令
查看参数的值

4.step及next命令
step可使得程序逐条执行,即执行完一条语句然后在下一跳语句前停下来,等待用户的命令。一般使用step命令是,可使用display或者watch命令查看变量的变化,从而判断程序行为是否符合要求。当下一条指令为函数时,s进入函数内部,在其第一条语句前停下来。next单步执行,但不进入函数内部。
step n,next n 表示连续但不执行n条指令,如果期间遇到断点,则停下来
5.print打印内部变量值
6.bt 查看堆栈信息
7.watch 监视变量值的变化

watch通常需要和break,run,continue联合使用。

下面举例说明:

代码如下:
#include <stdio.h>

int main()
{
int a=0;
for(int i=0; i<10; i++)
a+=i;
}
调试的时候过程如下:

(gdb) l
1 #include <stdio.h>
2
3 int main()
4 {
5 int a=0;
6 for(int i=0; i<10; i++)
7 a+=i;
8 }
(gdb) b 5 -------在第5行设置断电
Breakpoint 1 at 0x80483ba: file a.cpp, line 5.
(gdb) r -------执行到断点处停止
Starting program: /a.o

Breakpoint 1, main () at a.cpp:5
5 int a=0;
(gdb) watch a -------观察a的值,当有变化时,停止
Hardware watchpoint 2: a
(gdb) c -------继续执行,当a的值变化时停止
Continuing.
Hardware watchpoint 2: a

Old value = 0
New value = 1
main () at a.cpp:6
6 for(int i=0; i<10; i++)
(gdb)
Continuing.
Hardware watchpoint 2: a

Old value = 1
New value = 3
main () at a.cpp:6
6 for(int i=0; i<10; i++)
(gdb)
Continuing.
Hardware watchpoint 2: a

即,在使用watch时步骤如下:

  1. 使用break在要观察的变量所在处设置断点;

  2. 使用run执行,直到断点;

  3. 使用watch设置观察点;

  4. 使用continue观察设置的观察点是否有变化。

8.set variable value=x 动态改变变量值
1,调试中需要修改临时变量的值时,可以使用set命令
语法:

set variable key = value
set var key = value
示例:
(gdb) set variable array[1] = 12

2,另一种更简单的方式,使用print命令修改
语法:
print key=value

2.多线程调试

1. 线程的查看
首先创建两个线程:

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h> void* pthread_run1(void* arg)
{
(void)arg; while(1)
{
printf("I am thread1,ID: %d\n",pthread_self());
sleep(1);
}
} void* pthread_run2(void* arg)
{
(void)arg; while(1)
{
printf("I am thread2,ID: %d\n",pthread_self());
sleep(1);
}
} int main()
{ pthread_t tid1;
pthread_t tid2; pthread_create(&tid1,NULL,pthread_run1,NULL);
pthread_create(&tid2,NULL,pthread_run2,NULL); printf("I am main thread\n"); pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

分析:上面程序中创建了两个线程,程序执行起来,main函数所在程序为主线程,在这个主线程中有两个新线程运行。
命令行查看:

//查看当前运行的进程
ps aux|grep a.out
//查看当前运行的轻量级进程
ps -aL|grep a.out
//查看主线程和新线程的关系
pstree -p 主线程id
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6


2. 线程栈结构的查看

  1. 获取线程ID
  2. 通过命令查看栈结构 ps stack 线程ID

    3. 利用gdb查看线程信息
    将进程附加到gdb调试器当中,查看是否创建了新线程:gdb attach 主线程ID

查看线程的一些信息

//1.查看进程:info inferiors
//2.查看线程:info threads
//3.查看线程栈结构:bt
//4.切换线程:thread n(n代表第几个线程)

4. 利用gdb调试多线程
  当程序没有启动,线程还没有执行,此时利用gdb调试多线程和调试普通程序一样,通过设置断点,运行,查看信息等等,在这里不在演示,最后会加上调试线程的命令

设置断点

//1. 设置断点:break 行号/函数名
//2. 查看断点:info b
  • 1
  • 2


执行线程2的函数,指行完毕继续运行到断点处

1. 继续使某一线程运行:thread apply 1-n(第几个线程) n
2. 重新启动程序运行到断点处:r
  • 1
  • 2


3.只运行当前线程

. 设置:set scheduler-locking on 2
. 运行:n
  • 1
  • 2


4.所有线程并发执行

    1. 设置:set scheduler-locking off
2. 运行:n
  • 1
  • 2

注意点:
ctrl+c ctrl+d ctrl+z 的区别和使用场景

Ctrl+C :强制中断程序,程序无论运行哪里都停止。

Ctrl+D :发送一个 exit 的信号,退出当前的用户或者是客户端。

Ctrl+Z :暂停程序,在进程中维持挂起状态。

引用别人的说法:

1、Ctrl+C比较暴力,就是发送Terminal到当前的程序,比如你正在运行一个查找功能,文件正在查找中,Ctrl+C就会强制结束当前的这个进程。
2、Ctrl+Z 是把当前的程序挂起,暂停执行这个程序,比如你正在mysql终端中,需要出来搞点其他的文件操作,又不想退出mysql终端(因为下次还得输入用户名密码进入,挺麻烦),于是可以ctrl+z将mysql挂起,然后进行其他操作,然后输入 fg 回车后就可以回来,当然可以挂起好多进程到后台,然后 fg 加编号就能把挂起的进程返回到前台。当然,配合bg(后台)和fg命令进行前后台切换会非常方便。
3、Ctrl+D 是发送一个exit信号,没有那么强烈,类似ctrl+C的操作,比如你从管理员root退回到你的普通用户就可以这么用。

Linux学习——Gdb基本调试方法&&多线程调试的更多相关文章

  1. GDB:从单线程调试到多线程调试(MFiX单步调试)

    GDB:从单线程调试到多线程调试 1. 裸跑GDB 1.1 安装GDB sudo apt-get install gdb 1.2 编译程序 由于需要调试,因此编译的时候需要添加-g编译参数: 1.3 ...

  2. 2019-2-14-VisualStudio-通过外部调试方法快速调试库代码

    title author date CreateTime categories VisualStudio 通过外部调试方法快速调试库代码 lindexi 2019-2-14 22:1:37 +0800 ...

  3. Linux学习--gdb调试

    一.gdb常用命令: 命令 描述 backtrace(或bt) 查看各级函数调用及参数 finish 连续运行到当前函数返回为止,然后停下来等待命令 frame(或f) 帧编号 选择栈帧 info(或 ...

  4. Linux学习----gdb调试(指针的指针)

    昨天遇到一个很奇怪的问题,如下: 按照理论,最后*p的值应该是99,不知为什么是15了,所以今天记录用gdb调试的过程,并熟悉gdb的使用. (调试过程参考:http://www.cnblogs.co ...

  5. Linux学习笔记(16)-多线程

    什么是多线程?或者说,什么是线程? 按照书本上的描述,所谓线程,便是包含在进程内部的顺序执行流,是进程中实际运作的单位,也是操作系统能够进行调度的最小单位. 一个进程中可以并发多条线程,每条线程并行执 ...

  6. Linux学习笔记20——第一个多线程程序

    一 什么是线程 线程:是一个进程内部的一个控制序列. 二 使用POSIX的注意点 1 为了使用线程函数库,必须定义宏_REENTRANT,通过定义_REENTRANT来告诉编译器我们需要可重入功能,可 ...

  7. GDB多线程调试

    一.多线程调试1. 多线程调试,最重要的几个命令:info threads                        查看当前进程的线程.                              ...

  8. GDB调试方法精粹

    http://blog.chinaunix.net/uid-26922071-id-3756018.html 一.多线程调试 1. 多线程调试,最重要的几个命令: info threads       ...

  9. GDB多线程调试分析

    0x00: 在Linux系统上Gdb提供了一组多线程调试命令,如表所示: 多线程调试的主要任务是准确及时地捕捉被调试程序线程状态的变化的事件,并且GDB针对根据捕捉到的事件做出相应的操作,其实最终的结 ...

随机推荐

  1. [Beta]the Agiles Scrum Meeting 1

    会议时间:2020.5.9 21:00 1.每个人的工作 今天已完成的工作 讨论转会事项 经过组内成员的讨论,我们做出了非常艰难的决定:我们的组员老c将作为转会成员,离开我们的团队.感谢老c在Alph ...

  2. 大神教零基础入门如何快速高效的学习c语言开发

    零基础如果更快更好的入门C语言,如何在枯燥的学习中找到属于自己的兴趣,如果把学习当成一种事务性的那以后的学习将会很难有更深入的进步,如果带着乐趣来完成学习那将越学越有意思这样才会让你有想要更深入学习的 ...

  3. 同人逼死官方系列!基于sddc 协议的SDK框架 sddc_sdk_lib 解析

    基于sddc 协议的SDK框架 sddc_sdk_lib 解析 之前在移植 libsddc 库的时候感觉官方 demo 太低效了( ̄. ̄),复制粘贴代码好累,而且写出一个BUG,其他复制的代码整个就裂 ...

  4. Java 在PPT中创建散点图

    本文将以Java代码示例展示如何在PPT幻灯片中创建散点图表. 创建图表前 需要在Java程序中导入用于操作PPT的jar包 Free Spire.Presentation for Java.可参考如 ...

  5. QuantumTunnel:内网穿透服务设计

    背景 最近工作中有公网访问内网服务的需求,便了解了内网穿透相关的知识.发现原理和实现都不复杂,遂产生了设计一个内网穿透的想法. 名字想好了,就叫QuantumTunnel,量子隧道,名字来源于量子纠缠 ...

  6. ELK集群之filebeat(6)

    filebeat工作原理 ilebeat是本地文件的日志数据采集器. 作为服务器上的代理安装,Filebeat监视日志目录或特定日志文件,tail file,并将它们转发给Elasticsearch或 ...

  7. jacoco-统计代码覆盖率并生成报告

    一.概述: 作为一个合格的测试人员,保证产品的软件质量是其工作首要目标,为了这个目标,测试人员常常会通过很多手段或工具来加以保证,覆盖率就是其中一环比较重要的环节. 通常我们会将测试覆盖率分为两个部分 ...

  8. PyCharm Django Python 开发环境配置 详细教程

    PyCharm Django Python 开发环境配置 详细教程 1. Python 下载及安装 (1)根据需要的版本去 Python 官网(https://www.python.org/downl ...

  9. Robot Framework操作MySQL数据库

    1.安装databaselibrary.pymysql 通过cmd命令执行:pip install robotframework-databaselibrary cmd命令执行:pip install ...

  10. mysql 免密码登录

    mysql 8免密码登录 UPDATE mysql.user SET authentication_string=null WHERE User='root'; FLUSH PRIVILEGES; e ...