一、gdb常用指令:

gcc -g  main.c                      //在目标文件加入源代码的信息
gdb a.out       (gdb) start                         //开始调试
(gdb) n                             //一条一条执行
(gdb) step/s                        //执行下一条,如果函数进入函数
(gdb) backtrace/bt                  //查看函数调用栈帧
(gdb) info/i locals                 //查看当前栈帧局部变量
(gdb) frame/f                       //选择栈帧,再查看局部变量
(gdb) print/p                       //打印变量的值
(gdb) finish                        //运行到当前函数返回
(gdb) set var sum=0                 //修改变量值
(gdb) list/l 行号或函数名             //列出源码
(gdb) display/undisplay sum         //每次停下显示变量的值/取消跟踪
(gdb) break/b  行号或函数名           //设置断点
(gdb) continue/c                    //连续运行
(gdb) info/i breakpoints            //查看已经设置的断点
(gdb) delete breakpoints 2          //删除某个断点
(gdb) disable/enable breakpoints 3  //禁用/启用某个断点
(gdb) break 9 if sum != 0           //满足条件才激活断点
(gdb) run/r                         //重新从程序开头连续执行
(gdb) watch input[4]                //设置观察点
(gdb) info/i watchpoints            //查看设置的观察点
(gdb) x/7b input                    //打印存储器内容,b--每个字节一组,7--7组
(gdb) disassemble                   //反汇编当前函数或指定函数
(gdb) si                            // 一条指令一条指令调试 而 s 是一行一行代码
(gdb) info registers                // 显示所有寄存器的当前值
(gdb) x/20 $esp                    //查看内存中开始的20个数

二,调试子进程

实际上,GDB 没有对多进程程序调试提供直接支持。例如,使用GDB调试某个进程,如果该进程fork了子进程,GDB会继续调试该进程,子进程会不受干扰地运行下去。 如果你事先在子进程代码里设定了断点,子进程会收到SIGTRAP信号并终止。那么该如何调试子进程呢?其实我们可以利用GDB的特点或者其他一些辅助手 段来达到目的。此外,GDB 也在较新内核上加入一些多进程调试支持。

接下来我们详细介绍2种方法,分别是 follow-fork-mode 方法,attach 子进程方法。

在2.5.60版Linux内核及以后,GDB对使用fork/vfork创建子进程的程序提供了follow-fork-mode选项来支持多进程调试。

follow-fork-mode的用法为:

set follow-fork-mode [parent|child]

  • parent: fork之后继续调试父进程,子进程不受影响。
  • child: fork之后调试子进程,父进程不受影响。
  • 调试子进程时,设定在子进程上的断点将会有效,而父进程上的断点此时无效;反之依然。缺省gdb是调试主进程的

因此如果需要调试子进程,在启动gdb后,可以看到在启动之后自动跳转到了子进程代码中。

(gdb) set follow-fork-mode child
(gdb) start
16            pid = fork();
(gdb)
[New process 6238]
this is futher process 6236,wait child 6238
[Switching to process 6238]

Attach子进程

众所周知,GDB有附着(attach)到正在运行的进程的功能,即attach <pid>命令。因此我们可以利用该命令attach到子进程然后进行调试。

例如我们要调试某个进程OwnTest,首先得到该进程的pid

host-192-10-10-8:/home/code # ps -ef|grep OwnTest
root      8056  5964  0 14:06 pts/1    00:00:00 ./OwnTest
root      8057  8056  0 14:06 pts/1    00:00:00 ./OwnTest
root      8058  8057  0 14:06 pts/1    00:00:00 ./OwnTest
root      8067  8933  0 14:06 pts/0    00:00:00 grep OwnTest
查看之后发现是三进程,通过pstree查看父子进程id情况。
host-192-10-10-8:/home/code # pstree  8056
OwnTest───OwnTest───OwnTest
host-192-10-10-8:/home/code # pstree  8057
OwnTest───OwnTest

现在就可以调试了。一个新的问题是,子进程一直在运行,attach上去后都不知道运行到哪里了。有没有办法解决呢?

一个办法是,在要调试的子进程初始代码中,比如main函数开始处,加入一段特殊代码,使子进程在某个条件成立时便循环睡眠等待,attach到进程后在该代码段后设上断点,再把成立的条件取消,使代码可以继续执行下去。

至于这段代码所采用的条件,看你的偏好了。比如我们可以检查一个指定的环境变量的值,或者检查一个特定的文件存不存在。以文件为例,其形式可以如下:

void debug_wait(char *tag_file)
{while(1){if (tag_file存在)睡眠一段时间;elsebreak;}
}

三,调试线程

当程序没有启动,线程还没有执行,此时利用gdb调试多线程和调试普通程序一样,通过设置断点,运行,查看信息等等。

在多线程编程时,当我们需要调试时,有时需要控制某些线程停在断点,有些线程继续执行。有时需要控制线程的运行顺序。有时需要中断某个线程,切换到其他线程。这些都可以通过gdb实现。

先介绍一下GDB多线程调试的基本命令。

info threads
显示当前可调试的所有线程,每个线程会有一个GDB为其分配的ID,后面操作线程的时候会用到这个ID。
前面有*的是当前调试的线程。

thread ID
切换当前调试的线程为指定ID的线程。

thread apply ID1 ID2 command
让一个或者多个线程执行GDB命令command。

thread apply all command
让所有被调试线程执行GDB命令command。

set scheduler-locking off|on|step
估计是实际使用过多线程调试的人都可以发现,在使用step或者continue命令调试当前被调试线程的时候,其他线程也是同时执行的,怎么只让被调试程序执行呢?通过这个命令就可以实现这个需求。
off 不锁定任何线程,也就是所有线程都执行,这是默认值。
on 只有当前被调试程序会执行。
step 在单步的时候,除了next过一个函数的情况(熟悉情况的人可能知道,这其实是一个设置断点然后continue的行为)以外,只有当前线程会执行。

如果目标进程已经core dump了,那么 gdb -c core xxx   xxx是对应的程序文件。

如果目标进程还在运行,通常此时用于调试线程死锁的情况。有两种方法

一是 gdb -p xxx  xxx是该进程的进程ID

或者用gcore xxx先获取对应进程的core,他会生成一个core文件 core.xxx

进入gdb后

(gdb) info threads

可以列出所有的线程,缺省设为当前的线程前面有一个*号

比如

gdb) info thread
    9 system thread 154262  Priority:154  0xc00000000042f670:0 in __ksleep
   +0x30 () from /usr/lib/hpux64/libc.so.1
    4 system thread 153674  Priority:168  0xc0000000004367d0:0 in _nanosleep2_sys+0x30 () from /usr/lib/hpux64/libc.so.1
    3 system thread 153673  Priority:168  0xc0000000004367d0:0 in _nanosleep2_sys+0x30 () from /usr/lib/hpux64/libc.so.1
    2 system thread 153672  Priority:154  0xc00000000042f670:0 in __ksleep
   +0x30 () from /usr/lib/hpux64/libc.so.1
*   1 system thread 153671  Priority:154  0xc000000000432ef0:0 in _read_sys
   +0x30 () from /usr/lib/hpux64/libc.so.1

这是1个死锁的例子,可以看到线程9 和线程2都停在 __ksleep上。

如果想看各个线程的详细堆栈信息,比如要看9的

gdb)thread 9

把当前线程设成9,然后就可以查看相关信息

比如

gdb)bt

将列出栈的调用情况,以及对应源代码中的位置,此时谨慎察看对应代码,一般必有结果。

gdb 调试+子进程+线程相关推荐

  1. GDB 调试多进程或者多线程应用

    GDB 是 linux 系统上常用的 c/c++ 调试工具, 功能十分强大. 对于较为复杂的系统, 比如多进程系统, 如何使用 GDB 调试呢? 考虑下面这个三进程系统 : 进程 ProcessChi ...

  2. gdb调试fork+exec创建的子进程的方法

    最常见的多进程的形式如下: pid = fork(); if (pid < 0) { // fork failedprintf("fork error\n");exit(1) ...

  3. Linux基础 30分钟GDB调试快速突破

    引言 Linus心灵鸡汤 在*nix开发中有道卡叫gdb调试,不管你怎么搞. 它依然在那丝毫不会松动.今天致敬一个 活着的传奇 Linus Torvalds Unix 始于上个世纪60年代,在70年代 ...

  4. 比较全面的gdb调试命令

    用GDB调试程序  GDB是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形成执行序 列,形成脚本.UNIX下的软件全是命令行的,这给程序开发提代供了极大的便利,命令行 软件的优势在于 ...

  5. gdb调试多进程和多线程命令 .

    1. 默认设置下,在调试多进程程序时GDB只会调试主进程.但是GDB(>V7.0)支持多进程的 分别以及同时 调试,换句话说,GDB可以同时调试多个程序.只需要设置follow-fork-mod ...

  6. 多进程多线程GDB调试 (转)

    多进程多线程GDB调试   一.线程调试指南:   1. gdb attach pid 挂载到调试进程  2. gdb$ set scheduler-locking on 只执行当前选定线程的开关 3 ...

  7. 用gdb调试core文件

    GDB是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形成执行序列,形成脚本.UNIX下的软件全是命令行的,这给程序开发提代供了极大的便利,命令行软件的优势在于,它们可以非常容易的集成 ...

  8. 使用gdb调试多进程和多线程

    GDB调试多进程 1. 默认设置下,在调试多进程程序时GDB只会调试主进程.但是GDB(>V7.0)支持多进程的分别以及同时调试,换句话说,GDB可以同时调试多个程序.只需要设置follow-f ...

  9. GDB调试多进程|多线程程序

    1. 默认设置下,在调试多进程程序时GDB只会调试主进程.但是GDB(>V7.0)支持多进程的分别以及同时调试,换句话说,GDB可以同时调试多个程序.只需要设置follow-fork-mode( ...

最新文章

  1. 【 MATLAB 】z 变换中的卷积与解卷积
  2. socket传输过程
  3. Mozilla裁员波及Daala Codec团队
  4. java ndc_通过slf4j/log4j的MDC/NDC 实现日志追踪
  5. [ 转载 ] Java基础14--创建线程的两个方法
  6. 最短路径(信息学奥赛一本通-T1378)
  7. leetcode —— 209. 长度最小的子数组
  8. tomcat启动Configuration Error: deployment source ‘xxx:war exploded‘ is not valid
  9. 微课|玩转Python轻松过二级(1.3节):编码规范与代码优化建议2
  10. 1-java学习笔记
  11. ​四周第一次课(4月11日)lvm讲解
  12. 多次导入excel实现及excel导入逻辑插件清空数据
  13. 解决 Android App 上架 Google play后 ,签名变更,第三方sdk无法登录
  14. dataframe两个表合并_Spark实战第二版(涵盖Spark3.0)第三章 宏伟的角色dataframe
  15. ESP32s3-EYE ESP-IDF环境搭建Ubuntu18.04 Micropython环境搭建Pycharm 物联网
  16. OBS直播软件-简介
  17. 自定义控件其实很简单 五
  18. 2.Hadoop3.x 基础知识
  19. 拥有奇瑞QQ冰淇淋·桃欢喜才懂的幸福
  20. day11 - 每日总结及作业

热门文章

  1. 零基础学习SQL第一节
  2. 中国大学mooc 南京大学慕课 --探索数据的奥秘--代码复现
  3. 华为:研发协同,为什么说效率是第一重要的事儿?
  4. 雨林木风 Windows server 2003
  5. EMV中易混淆概念总结
  6. android,js,各种软件列表
  7. 互联网信息服务ICP许可证分类是什么?
  8. Hadoop(六)——子项目Pig
  9. java实现从http/https链接地址下载文件
  10. 香港服务器CDN加速与DDOS防御方案