GDB工具使用学习

参考和学习视频:
B站up主【拥有6块腹肌的程序猿的个人空间-哔哩哔哩】 https://b23.tv/rPiVDqX
视频地址:https://www.bilibili.com/video/BV1mp4y1A7Ss?vd_source=f8a6ae1f67ceef69d4edbdd3820288ec

GDB的一些基本命令

run:运行程序。可以带参数,例如 run arg1 arg2。

break:设置断点。可以在指定文件和行号上设置断点,或者在指定函数名处设置断点。

continue:继续执行程序,直到下一个断点或程序结束。

next:单步执行,逐过程地执行代码行(不进入函数内部)。

step:单步执行,逐语句地执行代码行(进入函数内部)。

print 或 p:打印变量的值。例如 print variable_name 或 p variable_name。

backtrace 或 bt:显示当前调用堆栈的跟踪信息,即显示函数调用关系。

info locals:显示当前函数的局部变量及其值。

info breakpoints 或 info b:列出当前已设置的所有断点。

delete breakpoints <编号>:删除指定编号的断点。可以使用 "info breakpoints" 命令查看已设置断点的编号。

GDB调试coredump文件

  1. coredump文件成为核心转储文件,存储进程运行时,突然崩溃的一瞬间的进程在内存中的一个快照(文件),包括此刻的内存、寄存器状态、运行堆栈等信息。
  2. 测试代码:
    //test.c
    #include <stdio.h>
    int main()
    {
        int *ptr = NULL;
        *ptr = 100; //崩溃在此处
        return 0;
    }

    编译:gcc -g -o test test.c

  3. 生成core文件:
    运行程序,出现如下输出:
  4. 没有core文件怎么办?
    注:博主使用Ubuntu20.04,仅供参考!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    参考步骤:

    1. 查看ulimit -c输出是否为unlimited,配置ulimit -c unlimited
    2. 步骤一完成后仍没有core文件,继续下面一系列操作:
      1. 查看文件:cat /proc/sys/kernel/core_pattern
          若输出为:|/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E
          继续下面操作,否则跳转到步骤2
          关闭apport服务:编辑文件/etc/default/apport,将enabled修改为1
      2. 编辑/etc/sysctl.conf文件,在文件末尾添加以下两行来设置core_uses_pid和core_pattern的值:
          kernel.core_uses_pid = 1
          # 用来控制core文件的生成
          kernel.core_pattern = /path/to/core/files/core.%p
          # 控制core文件在目录/path/to/core/files/下面。
          更新sysctl设置以使更改生效:
          sudo sysctl -p
    3. 永久修改ulimit -culimited
      打开终端并使用root权限登录或使用sudo命令。
      编辑/etc/security/limits.conf文件:
      sudo nano /etc/security/limits.conf
      在文件末尾添加以下行来设置core文件大小为unlimited:
      *               hard    core            unlimited
      *               soft    core            unlimited
      保存并关闭文件(在nano编辑器中按下Ctrl+X,然后按Y确认保存)。
      编辑/etc/pam.d/common-session文件:
      sudo nano /etc/pam.d/common-session
      在打开的文件中找到以下行并注释掉(在行前面添加#符号):
      #session required        pam_limits.so
      保存并关闭文件。
      重新启动系统以使更改生效。
      现在,ulimit -c将被永久设置为unlimited,允许生成任意大小的core转储文件。
  5. 调试core文件:
    1. 代码
      //测试程序
      //文件:test.c
      #include <stdio.h>
      #include <string.h>
      void func(char *ptr)
      {
          strcpy(ptr, "This is test code ..."); //此处崩溃
      }
      int main()
      {
          char *ptr = NULL;
          func(ptr);
          return 0;
      }
    2. 编译:gcc -g -o test test.c
    3. 运行:./test,输出:Segmentation fault (core dumped),生成core文件:core.6981(6981为pid);
    4. 调试命令:格式"gdb [程序] [core文件]",具体命令:gdb test core.6981
      输出:

      图中红框位置已经给出崩溃原因。
      输入:bt命令查看堆栈信息:

      可以看到当前函数栈有两个函数,分别为main函数和func函数。
      输入:f [函数栈编号]切换到对应函数栈,f 0:

      看到崩溃位置,可以看到func函数入参ptr0x0

      GDB调试多线程

  6. 调试多线程程序:

    1. 代码:

      //文件名:gdb_thread.c
      #include <stdio.h>
      #include <unistd.h>
      #include <pthread.h>
      
      void *thread_entry_funcA(void *arg)
      {
          int i = 0;
          for(i = 0; i < 10; i++)
          {
              printf("[thread_entry_funcA]: %d\n", i);
              sleep(1);
          }
          return NULL;
      }
      
      void *thread_entry_funcB(void *arg)
      {
          int i = 0;
          for(i = 0; i < 10; i++)
          {
              printf("[thread_entry_funcB]: %d\n", i);
              sleep(1);
          }
          return NULL;
      }
      
      int main()
      {
          pthread_t tidA, tidB;
          int ret = pthread_create(&tidA, NULL, thread_entry_funcA, NULL);
          if(ret < 0)
          {
              perror("pthread_ create");
              return 0;
          }
      
          ret = pthread_create(&tidB, NULL, thread_entry_funcB, NULL);
          if(ret < 0)
          {
              perror("pthread_ create");
              return 0;
          }
      
          pthread_join(tidA, NULL);
          pthread_join(tidB, NULL);
          return 0;
      }
    2. 编译和运行输出:
      编译:gcc -g -o gdb_thread gdb_thread.c -lpthread
      运行输出:
    3. 调试和查看线程信息:


      llist命令,用于查看代码。list命令会显示当前正在运行的代码周围的源代码行。默认情况下,list命令将会输出当前执行到的代码行以及前后的代码。
      l 10:显示第10行前后。
      list 1,10: 显示第1至第10行的代码。
      list main: 显示main函数中的代码。
      list foo: 显示foo函数中的代码。
      bbreakpoint,用于设置断点,即在程序的特定位置停止执行。

      在指定文件和行号上设置断点:
      break <文件名>:<行号>
      
      例如:break main.c:10 在main.c文件的第10行设置断点。
      
      在指定函数上设置断点:
      break <函数名>
      
      例如:break myFunction 在myFunction函数的入口处设置断点。
      
      在指定地址上设置断点:
      break *<地址>
      
      例如:break *0x12345678 在地址0x12345678处设置断点。
      
      条件断点:
      break <位置> if <条件>
      
      例如:break main.c:20 if i == 5 当变量i等于5时,在main.c文件的第20行设置断点。
      info breakpoint,简写:i b
      查看断点信息。

      图中两个断点,分别设置在第10行和第20行,断点信息为:

      (gdb) info b
      Num     Type           Disp Enb Address            What
      1       breakpoint     keep y   0x0000000000001209 in thread_entry_funcA at gdb_thread.c:10
      2       breakpoint     keep y   0x000000000000125d in thread_entry_funcB at gdb_thread.c:21

      运行程序:run 或 r


      停在了第10行,也就输第一个断点处。
      通过info threads命令查看全部线程信息

      *共有三个线程,前面有“”号的为当前正在执行的线程thread_entry_funcA,线程thread_entry_funcB初始化完成了
      输入t [线程id]切换至对应线程--t 3

      直接给出了断点信息。
      切换到对应线程后,通过bt命令查看当前线程的堆栈信息

      通过单步进行调试

      f 0切换到对应堆栈,n命令单步执行,打印出了[thread_entry_funcA]: 0,然后线程id为3的线程运行到断点2,打印一下变量i的值:p i,单步执行后打印了[thread_entry_funcB]: 0,再执行后又切换到线程id为2后运行到断点1,打印i值。**

    4. gdb中调度器锁
      调试时除了当前线程在运行,想要规定其他线程的运行情况,可以使用set scheduler-locking [mode]命令来进行设置。
      mode主要有三个选择:

      1. set scheduler-locking off:不锁定任何线程,所有线程都可以继续执行(遇见断点会停,也会出现上面调试某一线程时切换线程的情况。)
      2. set scheduler-locking on:只有当前线程可继续执行,其他线程暂停运行。
      3. set scheduler-locking step
        1. 当单步执行某一线程时,保证在调试过程中当前线程不会发生改变。其他线程也会随着被调试线程的单步执行而执行;
        2. 但如果该模式下执行continue、until、finish命令,则其他线程也会执行,并且如果某一线程执行过程中遇到断点,则GDB会将该线程作为当前线程(切换至对应线程)。
          查看调度器锁模式:show scheduler-locking.
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇
error: Content is protected !!内容保护!!