当前位置: 首页 > news >正文

C++(Qt)软件调试---gdb调试入门用法(12)

gdb调试—入门用法(1)

文章目录

  • gdb调试---入门用法(1)
    • 1、前言
      • 1.1 什么是GDB
      • 1.2 为什么要学习GDB
      • 1.3 主要内容
      • 1.4 GDB资料
    • 2、C/C++开发调试环境准备
    • 3、gdb启动调试
      • 1.1 启动调试并传入参数
      • 1.2 附加到进程
      • 1.3 过程执行
      • 1.4 退出调试
    • 4、gdb断点管理
      • 1.1 设置断点
      • 1.2 管理断点
    • 5、gdb的图形化界面功能
    • 6、gdb查看和修改变量
    • 7、gdb查看和修改内存的值
    • 8、查看修改寄存器
    • 9、gdb源代码查看、管理
    • 10、搜索源代码
    • 11、函数调用栈管理
    • 12、观察点
    • 13、gdb调试捕获点
    • 14、gdb生成core dump文件
    • 15、gdb调试core dump

更多精彩内容
👉个人内容分类汇总 👈
👉C++软件调试、异常定位 👈
👉GDB官方教程文档(英文) 👈
👉100个gdb小技巧 👈

1、前言

1.1 什么是GDB

GDB是GNU调试器的缩写,是一种用于调试程序的工具。

它可以帮助程序员在程序运行时检查程序的状态,查找程序中的错误和问题,并提供一些调试工具来帮助程序员更好地理解程序的行为。

GDB支持多种编程语言,包括C、C++、Go、Fortran和汇编语言等。

它可以在命令行界面或者图形界面下使用,并且可以在多种操作系统上运行,包括Linux、Unix、Windows等。

GDB的主要作用包括以下几个方面:

  1. 检查程序状态:GDB可以帮助程序员在程序运行时检查程序的状态,包括变量的值、函数的调用栈、程序的执行流程等。
  2. 查找程序错误和问题:GDB可以帮助程序员更快地找到程序中的错误和问题,提高程序的质量和稳定性。
  3. 设置断点:GDB可以设置断点,让程序在特定的位置停下来,以便程序员检查程序的状态。
  4. 提供调试工具:GDB还提供了一些调试工具,如单步执行、查看内存、查看寄存器等,帮助程序员更好地理解程序的行为。

总之,GDB是一种非常强大的调试工具,可以帮助程序员更快地找到程序中的错误和问题,提高程序的质量和稳定性。

1.2 为什么要学习GDB

学习GDB可以帮助程序员更好地调试程序,找到程序中的错误和问题,提高程序的质量和稳定性。

在开发大型软件时,程序中可能存在许多错误和问题,这些问题可能会导致程序崩溃或者出现不可预期的行为。

使用GDB可以帮助程序员更快地找到这些问题,并且提供一些调试工具来帮助程序员更好地理解程序的行为。

此外,学习GDB还可以提高程序员的调试能力,让他们更加熟练地使用调试工具,提高工作效率。

因此,学习GDB是非常有必要的。

1.3 主要内容

  1. linux C/C++开发调试环境准备;
  2. GDB调试基本功能介绍;
    • 调试执行;
    • 断点管理;
    • 线程管理;
    • 调用栈管理;
    • 查看修改变量;
    • 其它基本功能;
  3. 多线程死锁调试;
  4. 动态库调试;
  5. 内存检查
    • 内存泄漏;
    • 堆栈溢出;
    • 删除后继续使用;
  6. 远程调试;
  7. Core dump调试分析;
  8. 发行版调试。

1.4 GDB资料

GDB:GNU 工程调试器 (sourceware.org)

顶部(使用 GDB 调试) (sourceware.org)

2、C/C++开发调试环境准备

  • 在ubuntu中使用下 列命令安装C++开发调试环境

    sudo apt install g++ gcc make gdb
    

3、gdb启动调试

1.1 启动调试并传入参数

  • 测试代码

    #include<iostream>using namespace std;int func(int x)
    {int sum = 0;for(int i = 0; i < x; i++){sum += i;}return sum;
    }int main(int argc, char** argv)
    {for(int i = 1; i < argc; i++){cout << "传入参数:" << i <<" " << argv[i] << endl;}int a = 0;int x = 0;if(argc > 1){x = atoi(argv[1]);}a = func(x);cout << x << " " << a << endl;return 0;
    }
  • gdb --args <executable> <arguments>
    • 在启动 GDB 调试器时指定程序及其参数;
    • “gdb --args” 是 GNU Debugger (gdb) 命令的一部分,用于在调试程序时指定要调试的可执行文件和其参数
    • 使用此命令可以将可执行文件和参数作为一个整体传递给 gdb。
    • 其中,“” 是要调试的可执行文件的路径和名称,“” 是要传递给可执行文件的命令行参数,多个参数之间以空格分隔。
  • set args <args>
    • gdb --args类似,不过是在 GDB 内部执行的命令(gdb启动后),用于修改当前正在调试的程序的命令行参数。
    • 使用 gdb set args 可以多次修改参数,而使用 gdb --args 只能在启动时设置一次。
    • 如果要调试的程序中包含空格或其他特殊字符,则必须使用引号或转义字符来正确指定参数。
  • r <args>
    • r是run的缩写,run命令用于启动程序;
    • r 用于启动程序并传递命令行参数,类似于set args + run。

在这里插入图片描述

  • 命令中的-q是用于关闭启动时的提示信息。

1.2 附加到进程

  • 什么是附加到进程调试

    附加到进程调试是一种调试技术,它允许开发人员在程序运行时观察和分析程序的内部状态。

    通常,在调试过程中,开发人员会在代码中设置断点,以便在程序执行到特定位置时停止并检查其状态。但是,有时候问题可能只在程序运行的特定环境中出现,或者只在特定条件下才能复现。这时,附加到进程调试就非常有用了。

    附加到进程调试的过程通常包括以下几个步骤:

    1. 打开调试器:首先,开发人员需要打开一个调试器,例如Visual Studio、GDB或LLDB等。调试器是一个用于观察和控制程序执行的工具。
    2. 选择进程:开发人员需要选择要附加调试的进程。这可以是正在运行的本地程序,也可以是远程计算机上的程序。
    3. 设置断点:开发人员可以在代码中设置断点,以便在程序执行到特定位置时停止。断点可以设置在函数调用、条件语句、循环等位置。
    4. 开始调试:一旦选择了进程并设置了断点,开发人员就可以开始调试了。调试器会监视程序的执行,并在断点处停止程序。
    5. 观察和分析:当程序停止在断点处时,开发人员可以观察和分析程序的内部状态,例如变量的值、函数的调用堆栈等。这有助于理解程序的行为和找出问题所在。
    6. 继续执行:在观察和分析完程序的内部状态后,开发人员可以选择继续执行程序,直到下一个断点或程序结束。

    附加到进程调试是一种强大的调试技术,可以帮助开发人员快速定位和解决程序中的问题。它在软件开发和故障排除过程中非常常见和重要。

  • 下面三条命令的主要区别在于语法的不同,但它们的功能是相同的。你可以使用gdb的各种命令来控制调试过程,例如"break"设置断点,"run"开始执行程序,"next"单步执行等等。

  • 请注意,附加到正在运行的进程可能会对其产生一些影响,因此请谨慎使用。此外,附加到进程可能需要root权限或者对进程的所有者具有适当的权限。

  • 是想要附加的进程的进程ID。附加成功后,gdb将会连接到该进程,并允许你使用gdb的调试功能来检查进程的状态、设置断点、单步执行等操作。

    • gdb attach <PID>
    • gdb --pid=<PID>
    • gdb -p <PID>
  • 测试代码

    #include <iostream>int main() 
    {int num;std::cout << "请输入一个整数:";std::cin >> num;int a;a = num + 1;int b;b = num * 10;std::cout << a <<" " << b << std::endl;std::cout << "您输入的整数是:" << num << std::endl;return 0;
    }
  • 演示如下

    1. 使用命令g++ test2.cpp -g编译代码,加上-g生成包含调试详细的可执行程序;
    2. 运行可执行程序;
    3. 使用命令cat -n test2.cpp 查看源代码;
    4. 使用命令ps -aux | grep a.out查看名称为a.out的进程的pid号;
    5. 进程的pid号;
    6. 使用命令 sudo gdb -q -p 9834将gdb附加到pid号为9834的进程进行调试,需要使用超级用户权限;
    7. 使用命令b test2.cpp:8在test2.cpp文件的第8行打一个断点;
    8. 继续执行gdb,c命令是continue的缩写,用于继续执行程序直到下一个断点或程序结束;
    9. 单步执行gdb,n命令是next的缩写,用于执行下一行代码。当程序被暂停在某个断点处时,可以使用n命令来执行下一行代码,而不会进入函数调用。这个命令通常用于逐行执行程序,以便观察程序的执行流程。

    在这里插入图片描述

1.3 过程执行

  • 常用过程执行命令

    • start:启动程序并暂停main函数的第一行,让程序在调试器中开始执行,而不是直接运行。
    • next(简写为n):执行下一行代码,并将控制权移动到下一行,遇见函数调用会跳过,如果调用的函数中有断点则会进入。
      • n:简写形式,执行下一行代码。
      • next:执行下一行代码。
      • next n:执行下n行代码。
      • nexti:执行下一条机器指令。
      • nexti n:执行下n条机器指令。
    • step [count](简写为s):执行下一行代码,并将控制权移动到下一行。如果当前行是函数调用,会进入该函数并在第一行暂停。
      • 其中,count是一个可选参数,表示要执行的行数。如果不指定count,则默认为1,即执行一行。
    • finish:执行完当前函数的剩余代码,并将控制权返回到调用该函数的地方
    • continue(简写为c):继续执行程序,直到遇到下一个断点或程序结束
  • 测试代码

    #include<iostream>using namespace std;int sumFun(int size)
    {int sum = 0;for(int i = 0; i < size; i++){sum += i;}return sum;
    }int main()
    {int size = 10;int sum = 0;sum = sumFun(size);cout << "计算从0到" << size <<" 的和为:" << endl;cout << sum << endl;size = 100;sum = sumFun(size);cout << "计算从0到" << size <<" 的和为:" << endl;cout << sum << endl;return 0;
    }
    
  • 演示

    在这里插入图片描述

1.4 退出调试

  • 退出调试方式
    • quit:缩写q这是最常用的退出命令,它会立即终止gdb会话并退出到终端。
    • Ctrl + D:这是一个快捷键组合,按下Ctrl和D键后,gdb会话会立即终止并退出到终端。
    • detach:用于将gdb与正在调试的程序分离,使得程序可以在后台继续运行,而不受gdb的控制。这在某些情况下非常有用,比如当你想让程序在调试过程中继续执行一段时间,而不需要gdb的干预。

4、gdb断点管理

  • 测试代码

    #include <iostream>using namespace std;int fun1()
    {int a = 10;int b = 20;throw a;return b;
    }int fun2(int a)
    {int b = 0;b = a + 10;return b;
    }
    int main()
    {cout <<"调用函数2" << endl;int a = 10;cout << fun2(a) << endl;cout << "调用函数1" << endl;try{fun1();}catch(...){cout <<"出现异常" << endl;}return 0;
    }
    

1.1 设置断点

  • 设置断点命令

    1. break:设置断点,缩写为b
      • 行号断点:使用break命令加上源代码的行号可以在指定行上设置断点。例如,break 10会在第10行设置一个断点;
      • 函数断点:使用break命令加上函数名可以在指定函数入口处设置断点。例如,break myFunction会在myFunction函数的入口处设置一个断点,如果是类或者命名空间则需要加上作用域;
      • 条件断点:使用break命令加上条件可以在满足条件时设置断点。例如,break myFunction if i == 10会在myFunction函数的入口处设置一个断点,但只有当变量i的值等于10时才会触发断点;
      • 内存地址断点:使用break命令加上内存地址可以在指定内存地址处设置断点。例如,break *0x12345678会在内存地址0x12345678处设置一个断点,当调试汇编程序,或者没有调试信息的程序时,经常需要在程序地址上打断点,可以使用disassemble命令查看程序的反汇编后的地址;
      • 指令断点:使用break命令加上指令地址可以在指定指令处设置断点。例如,break *0x12345678会在指令地址0x12345678处设置一个断点;
    2. tbreak:命令用于设置临时断点,缩写为tb。与break命令不同,临时断点只会在程序执行到该断点时触发一次,然后自动被删除。您可以使用tbreak命令后跟函数或行号来设置临时断点。
    3. rbreak:设置正则表达式断点,缩写为rb
      • 语法rbreak [regexp],其中,regexp是一个正则表达式,用于匹配要设置断点的函数名。rbreak命令会在所有可执行文件中搜索匹配的函数名,并在每个匹配的函数入口处设置断点;
      • 设置所有函数名以"foo"开头的断点: rbreak ^foo
      • 设置所有函数名以"bar"结尾的断点: rbreak bar$
      • 设置所有函数名中包含"baz"的断点: rbreak baz
    4. catch:catch命令用于设置异常断点。
      • 异常断点会在程序抛出异常时触发。您可以使用catch命令后跟异常类型来设置异常断点;
      • 语法catch [exception] [command]
      • exception:是要捕获的异常类型,可以是以下几种:
        • throw:捕获由C++程序中的throw语句引发的异常。
        • catch:捕获由C++程序中的catch语句处理的异常。
        • exec:捕获由被调试程序中的exec调用引发的异常。
        • fork:捕获由被调试程序中的fork调用引发的异常。
        • vfork:捕获由被调试程序中的vfork调用引发的异常。
        • syscall:捕获由被调试程序中的系统调用引发的异常。
      • command:是在捕获到异常时要执行的命令。如果省略command,则gdb会在捕获到异常时停止程序的执行并显示相关信息。
    5. trace:用于设置跟踪点。
      • 跟踪点是一种特殊的断点,它可以在程序执行到指定的函数或行号时触发,并显示函数的参数和返回值。
      • 跟踪点可以帮助开发人员更详细地了解程序的执行过程,以便更好地调试和分析代码。
  • 演示

    在这里插入图片描述

1.2 管理断点

  • gdb断点管理常用命令

    1. delete:删除断点。会从断点列表中删除指定的断点,但不会清除程序中的断点位置。如果再次运行程序,断点仍然会被触发。

      • 缩写为d

      • 删除所有断点:使用delete命令后不加任何参数,即可删除所有已设置的断点。

      • 删除指定编号的断点:每个断点都有一个唯一的编号,可以使用delete命令后加上断点编号来删除指定的断点。例如delete 1

      • 删除所有在指定函数中设置的断点:可以使用delete命令后加上函数名来删除所有在该函数中设置的断点。例如 delete function_name

      • 删除所有在指定文件中设置的断点:可以使用delete命令后加上文件名来删除所有在该文件中设置的断点。例如:delete file_name

      • 删除所有在指定行号处设置的断点:可以使用delete命令后加上行号来删除所有在该行号处设置的断点。例如delete line_number

      • 需要注意的是,删除断点时需要确保当前正在调试的程序处于暂停状态,否则删除操作可能无效。可以使用info breakpoints命令来查看当前已设置的断点,并获取它们的编号以及其他相关信息。

    2. clear:清除断点。会从程序中清除指定的断点位置,这意味着即使再次运行程序,断点也不会被触发。

      • 清除所有断点:使用clear命令后不跟任何参数,可以清除所有已设置的断点。
      • 清除指定行号的断点:使用clear命令后跟上要清除断点的源文件名行号,可以清除指定行号的断点。例如,clear main.cpp:10可以清除main.cp文件中第10行的断点。
      • 清除指定函数的断点:使用clear命令后跟上要清除断点的函数名,可以清除指定函数的断点。例如clear my_function可以清除名为my_function的函数的断点。
      • 清除指定源文件的断点:使用clear命令后跟上要清除断点的源文件名,可以清除指定源文件的所有断点。例如,clear main.cpp可以清除main.cp文件中的所有断点。
    3. disable:禁用断点、观察点或线程。

      • 语法:disable [breakpoint|watchpoint|thread] <编号>

        • breakpoint表示断点;
        • watchpoint表示观察点;
        • thread表示线程;
        • <编号>是要禁用的断点、观察点或线程的编号。
      • 可以使用disable命令后跟断点号来禁用特定的断点,例如disable 1

    4. enable:用于启用断点。

      • 可以使用enable命令后跟断点号来启用特定的断点,例如enable 1
    5. info breakpoints:显示当前设置的所有断点。

      • 缩写为i b
      • 使用info breakpoints命令可以查看当前设置的所有断点的详细信息,包括断点号、断点类型、断点位置等。
  • 演示

    在这里插入图片描述

5、gdb的图形化界面功能

gdb中的tui是指Text User Interface,它是gdb的一个可选功能,用于在终端中以图形化的方式显示源代码、汇编代码和调试信息。

tui提供了一个类似于文本编辑器的界面,可以在调试过程中更方便地查看和操作代码。

使用tui可以在终端中同时显示源代码和调试信息,以及当前执行的代码行。

它可以帮助开发人员更直观地理解代码的执行流程,快速定位问题。

启动tui功能的方式:

  1. 启动gdb时使用命令gdb -tui 可执行程序
  2. 在gdb命令行中输入命令tui enable
  3. 在gdb命令行中使用快捷键Ctrl x a

关闭tui功能的方式:在gdb命令行中输入命令tui disable

启用tui后,可以使用以下命令来操作:

  • layout src:显示源代码窗口。
  • layout asm:显示汇编代码窗口。
  • layout regs:显示寄存器窗口。
  • layout split:将源代码窗口和汇编代码窗口分割显示。
  • layout next:切换到下一个布局。
  • layout prev:切换到上一个布局。
  • focus next:将焦点切换到下一个窗口。
  • focus prev:将焦点切换到上一个窗口。
  • 使用gdb图形化调试界面时,可以使用“winheight <win_name> [+ | -]count”命令调整窗口大小(winheight缩写为winwin_name可以是srccmdasmregs)。
    • 例如:win src -5

此外,还可以使用其他gdb命令来设置断点、单步执行代码等。

需要注意的是,gdb的tui功能在不同的终端和操作系统上可能会有一些差异,具体的使用方法和快捷键可能会有所不同。可以通过在gdb命令行中输入help tui来获取更详细的帮助信息。

  • 演示:使用命令打的断点在tui窗口中可以实时看见。

    在这里插入图片描述

6、gdb查看和修改变量

  • 测试代码

    #include<iostream>using namespace std;int g_a = 10;
    char g_b = 'a';int func(int x)
    {int sum = 0;for(int i = 0; i < x; i++){sum += i;}return sum;
    }struct Test{int a = 10;char b = 'c';double c = 123.321;
    };int main(int argc, char** argv)
    {for(int i = 1; i < argc; i++){cout << "传入参数:" << i <<" " << argv[i] << endl;}int a = 0;int x = 0;char str[] = "hello";if(argc > 1){x = atoi(argv[1]);}a = func(x);cout << x << " " << a << endl;Test t;cout << "结构体" << endl;return 0;
    }
  • 常用命令

    1. info locals:显示当前栈帧的局部变量的值。
    2. info args:gdb将会显示出当前函数的参数列表及其对应的值。这些参数包括函数的形参名称以及实际传递给函数的值。
    3. info variables:这个命令将显示当前作用域中所有变量的列表,包括全局变量。
    4. print variable_name:这个命令将显示指定变量的值。(缩写为p)
    5. set print null-stop:设置字符串的显示规则,显示字符串时遇见\0就停止输出;
    6. set print pretty:显示结构体,结构体换行输出;
    7. set print array on:显示数组;
    8. p 变量名=value:修改变量值为value;
    9. set var 变量名=value:修改变量值为value;
    10. set main::str = "hello":修改字符串的值,需要注意内存越界;
  • 演示

    在这里插入图片描述

7、gdb查看和修改内存的值

  • 测试代码

    #include <iostream>using namespace std;int main()
    {int a = 10;char c = 'a';return 0;
    }
  • 查看内存

  • x/[格式 长度] 地址

  • 格式字母有:

    • o(八进制)
    • x(十六进制)
    • d(十进制)
    • u(无符号十进制)
    • t(二进制)
    • f(浮点)
    • a(地址)
    • i(指令)
    • c(字符)
    • s(字符串)
    • z(十六进制,左边加零)。
  • 大小字母有

    • b:以字节为单位显示数据。
    • h:以半字(2字节)为单位显示数据。
    • w:以字(4字节)为单位显示数据。
    • g:以双字(8字节)为单位显示数据。
  • 设置内存

    • set {type}address=value
    • address:存储地址;
    • type:变量类型;
    • value:需要设置的值。
  • 演示

    在这里插入图片描述

8、查看修改寄存器

  • 测试代码

    #include <iostream>using namespace std;int fun(const char* name, int age)
    {cout << name <<" " << age << endl;return 0;
    }int main()
    {fun("hello", 123);return 0;
    }
  • 使用命令

    • info registers:用于显示当前正在被调试程序的寄存器状态。它会列出各个寄存器的名称和当前的值。
    • info r rdi:查看单个寄存器rdi;
  • 函数参数的寄存器

    寄存器函数参数
    rdi第一个参数
    rsi第二个参数
    rdx第三个参数
    rcx第四个参数
    r8第五个参数
    r9第六个参数
  • 演示:没有调试符号时可以通过查看寄存器来进行调试。

    在这里插入图片描述

  • 修改寄存器命令

  • set var $pc=value:修改pc寄存器,pc寄存器是一种用于存储即将被执行的指令地址的寄存器。它通常用于计算机的中央处理器(CPU)中,在执行程序时起到指示下一条要执行的指令的作用。

  • 演示

    • 使用b fun在fun函数打一个断点;
    • 使用r命令运行程序,停在断点处;
    • 使用info line 8命令查看第8行代码的地址;
    • 使用set var &pc=0x5555555551e3将pc寄存器执行的下一条指令修改为第8行代码;
    • 使用n命令单步执行,程序直接跳转到第8行,跳过了int a = 10这一行代码。

    在这里插入图片描述

9、gdb源代码查看、管理

  • 测试代码

    • main.cpp

      /********************************************************************************
      * 文件名:   main.cpp
      * 创建时间: 2023-07-26 20:14:04
      * 开发者:   MHF
      * 邮箱:     1603291350@qq.com
      * 功能:     
      *********************************************************************************/
      #include<iostream>
      #include "test.h"using namespace std;int main()
      {int a = 10;int b = 20;int sum = 0;test t;t.setValue(a, b);sum = t.getSum();cout << sum << endl;return 0;
      }
      
    • test.h

      #pragma oneclass test
      {
      private:int m_a = 0;int m_b = 0;public:test(/* args */);~test();void setValue(int a, int b);int getSum();
      };
    • test.cpp

      #include "test.h"test::test(/* args */)
      {
      }test::~test()
      {
      }void test::setValue(int a, int b)
      {m_a = a;m_b = b;
      }int test::getSum()
      {return m_a + m_b;
      }
      
  • 使用命令

    • list:缩写为l,它用于显示源代码,并帮助程序员在调试过程中理解代码的执行流程。
    • 语法:list [function] [start-line [end-line]]
      • function(可选):指定要显示源代码的函数名或方法名。如果不指定,则显示当前默认的函数或方法的源代码。
      • start-line(可选):指定要从哪一行开始显示源代码。如果不指定,则默认从当前上下文中的下一行开始显示。
      • end-line(可选):指定要到哪一行结束显示源代码。如果不指定,则默认显示从起始行开始的十行代码。
    • 使用示例
      • list:显示当前函数或方法的源代码,默认从下一行开始,显示十行代码。
      • list main:显示名为"main"的函数的源代码,默认从下一行开始,显示十行代码。
      • list main 10:显示名为"main"的函数的源代码,从第10行开始,显示十行代码。
      • list main.cpp:15:显示指定文件的指定行代码。
      • list file:fun:显示指定文件中的指定函数代码;
      • list class:fun:显示指定类的成员函数代码。
    • set listsize xx:设置每次显示的代码行数。
  • 演示

    在这里插入图片描述

10、搜索源代码

  • 使用命令
    • search str:在当前文件中查找包含str字符串的行;
    • forward-search str:向后查找;
    • reverse-search str:向前查找。

11、函数调用栈管理

  • 测试代码

    #include <iostream>using namespace std;void fun1()
    {int a = 10;int* b = nullptr;*b = a;
    }void fun2()
    {char c = 'a';cout << c << endl;fun1();
    }int main()
    {fun2();return 0;
    }
  • 使用命令

    1. backtrace命令:显示当前的函数调用栈。可以在程序崩溃或中止时使用,用来追踪函数调用链以确定程序执行到哪里。缩写为bt
    2. updown命令:在当前函数调用链中向上或向下切换。
      • up : 切换到调用当前函数的函数
      • down:切换回当前函数
      • up n :向上选择函数堆栈帧,其中n是层数
      • down n:切向下选择函数堆栈帧,其中n是层数
    3. frame命令:切换到指定的栈帧(Stack Frame)。
      • 先使用backtrace查看栈帧列表
      • 在使用frame 2 切换到第3个栈帧
    4. info frame命令:显示当前栈帧的详细信息,包括函数调用点、参数、局部变量等。
      • info frame :查看当前栈帧信息
      • info frame 3 :查看id为3的栈帧信息
  • 演示

    在这里插入图片描述

12、观察点

  • watch: watch 命令允许您监视一个变量或一个表达式的值,并在其值发生更改时暂停程序的执行。您可以使用 watch 命令来跟踪特定变量的变化,以便在发生错误或特定事件时检查它们的值。

    • watch a
    • watch a == 10:观察点可以带有条件。条件可以使观察点仅在满足特定条件时触发。例如,要在变量x的值为10时触发观察点;
    • watch a thread 1:指定只有线程1写变量a时触发;
  • rwatch:rwatch 命令也是用于监视变量或表达式的值,但它只在读取(而不是写入)该值时触发断点。这对于跟踪对某个变量的读取很有用,以确认某些代码段是否访问了它。

  • awatch: awatch 命令可用于监视变量或表达式的读取写入操作。当变量或表达式的值发生变化时,程序将在读取或写入操作上暂停执行。

  • info watch:查看观察点;

  • delete:删除观察点;

  • disable:禁用观察点;

  • enable:弃用观察点;

  • 测试代码

    #include <iostream>using namespace std;int main()
    {int a = 10;char c = 'a';return 0;
    }
  • 演示

    在这里插入图片描述

13、gdb调试捕获点

  • 捕获点是一个特殊的断点,命令语法为:catch event

  • 即捕获到event这个事件的时候,程序就会中断下类;

  • 支持的捕获事件有:(可以在gdb中使用help catch命令查看)

    事件说明
    catch assertCatch在引发时失败的Ada断言。
    catch catch当程序捕获异常时触发捕获点。可以用来跟踪异常的捕获过程。
    catch exceptionCatch Ada异常,当引发时。
    catch exec捕获对exec的调用。
    catch fork捕获对fork的调用。
    catch handlers处理时捕获Ada异常。
    catch load捕获共享库的负载。
    catch rethrow重新引发时捕获异常。
    catch signal通过信号的名称和/或编号捕捉信号。
    catch syscall通过系统调用的名称、组和/或号码捕获系统调用。
    catch throw抛出时捕获异常
    catch unload捕获共享库的卸载。
    catch vfork捕获对vfork的调用。
  • 测试代码

    #include<iostream>using namespace std;void fun()
    {int a = 1;cout << a << endl;throw a;
    }int main()
    {try{fun();}catch(int a){cout << "捕获:" << a << endl;}
    }
  • 演示

    在这里插入图片描述

14、gdb生成core dump文件

  • 测试代码

  • 使用命令

    • generate-core-file:gcore 类似,generate-core-file 命令也用于在 gdb 中生成核心转储文件,可以单独使用命令,也可以在generate-core-file后跟文件路径文件名称。
    • gcore:在正在运行的进程中,使用 gcore 命令可以生成一个称为核心转储文件(core dump)的文件。这个核心转储文件包含了进程在崩溃时的内存状态、寄存器信息等,有助于开发人员分析程序崩溃的原因。
  • 使用示例

    在这里插入图片描述

15、gdb调试core dump

  • 测试代码

  • 方法1:使用gdb 可执行程序 core文件命令加载调试core dump;

  • 方法2:使用gdb 可执行程序命令进入gdb后,使用core core文件名命令指定core文件,进行调试;

  • 演示

    在这里插入图片描述

相关文章:

C++(Qt)软件调试---gdb调试入门用法(12)

gdb调试—入门用法&#xff08;1&#xff09; 文章目录 gdb调试---入门用法&#xff08;1&#xff09;1、前言1.1 什么是GDB1.2 为什么要学习GDB1.3 主要内容1.4 GDB资料 2、C/C开发调试环境准备3、gdb启动调试1.1 启动调试并传入参数1.2 附加到进程1.3 过程执行1.4 退出调试 4…...

shell和Python 两种方法分别画 iostat的监控图

在服务器存储的测试中,经常需要看performance的性能曲线&#xff0c;这样最能直接观察HDD或者SSD的性能曲线。 如下这是一个针对HDD跑Fio读写的iostat监控log,下面介绍一下分别用shell 和Python3 写画iostat图的方法 1 shell脚本 环境:linux OS gnuplot工具 第一步 :解析iosta…...

设计模式(9)建造者模式

一、 1、概念&#xff1a;将一个复杂对象的构造与它的表示分离&#xff0c;使得同样的构造过程可以创建不同的表示。建造者模式主要用于创建一些复杂的对象&#xff0c;这些对象内部构建间的顺序通常是稳定的&#xff0c;但对象内部的构建通常面临着复杂的变化&#xff1b;建造…...

PHP 创业感悟交流平台系统mysql数据库web结构apache计算机软件工程网页wamp

一、源码特点 PHP 创业感悟交流平台系统&#xff08;含论坛&#xff09;是一套完善的web设计系统&#xff0c;对理解php编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 源码下载&#xff1a; https://download.csdn.…...

工作流程引擎之flowable(集成springboot)

0、背景 现状&#xff1a;公司各部门业务系统有各自的工作流引擎&#xff0c;也有cross function的业务在不同系统或OA系统流转&#xff0c;没有统一的去规划布局统一的BPM解决方案&#xff0c;近期由于一个项目引发朝着整合统一的BPM方案&#xff0c;特了解一下市面上比较主流…...

leetcode54. 螺旋矩阵(java)

螺旋矩阵 题目描述解题 收缩法 上期经典算法 题目描述 难度 - 中等 原题链接 - leecode 54 螺旋矩阵 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7…...

go gorm 查询

定义model package mysqltestimport ("errors""fmt""gorm.io/gorm" )type Product struct {gorm.ModelID uint gorm:"primarykey"Name string gorm:"column:name"Price float64 gorm:"column:price_value&quo…...

Flutter GetXController 动态Tabbar 报错问题

场景&#xff1a; 1.Tabbar的内容是接口获取的 2. TabController? tabController;&#xff1b; 在onInit 方法中初始化tabbarController tabController TabController(initialIndex: 0, length: titleDataList.length, vsync: this); 这时候会报一个错误 Controllers l…...

Redis(缓存预热,缓存雪崩,缓存击穿,缓存穿透)

目录 一、缓存预热 二、缓存雪崩 三、缓存击穿 四、缓存穿透 一、缓存预热 开过车的都知道&#xff0c;冬天的时候启动我们的小汽车之后不要直接驾驶&#xff0c;先让车子发动机预热一段时间再启动。缓存预热是一样的道理。 缓存预热就是系统启动前&#xff0c;提前将相关的…...

UE4/5Niagara粒子特效学习(使用UE5.1,适合新手)

目录 创建空模板 创建粒子 粒子的基础属性 粒子的生命周期 颜色 大小设置 生成的位置 Skeletal Mesh Location的效果&#xff1a; Shape Location 添加速度 添加Noise力场 在生成中添加&#xff1a; 效果&#xff1a; ​编辑 在更新中添加&#xff1a; 效果&…...

from moduleA import * 语句 和import moduleA 的区别

from moduleA import * 语句和import moduleA 的区别是&#xff1a; from moduleA import * 语句会将moduleA模块中的所有内容&#xff08;函数、变量、类等&#xff09;直接导入到当前模块的命名空间中&#xff0c;这样就可以直接使用它们&#xff0c;而不需要加上模块名的限…...

【leetcode 力扣刷题】交换链表中的节点

24. 两两交换链表中的节点 24. 两两交换链表中的节点两两节点分组&#xff0c;反转两个节点连接递归求解 24. 两两交换链表中的节点 题目链接&#xff1a;24. 两两交换链表中的节点 题目内容&#xff1a; 题目中强调不能修改节点内部值&#xff0c;是因为如果不加这个限制的话…...

学会Mybatis框架:让你的代码更具灵活性、可维护性、安全性和高效性【二.动态SQL】

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Mybatis的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Mybatis动态SQL如何应用 1.需求 2.…...

Oracle 中 ROWNUM 使用问题记录

ROWNUM 使用问题记录(2023-08-17) Oracle 版本&#xff1a; 19.0.0.0.0 Enterprise现象&#xff1a;今天在项目遇到一个问题&#xff0c;测试人员反馈前一天能看到的数据今天看不到了 用表格举例&#xff0c;这是前一天看到的数据&#xff0c;有9、7、1 这几个数量信息 日期…...

MySQL数据库:内置函数

日期函数 规定&#xff1a;日期&#xff1a;年月日 时间&#xff1a;时分秒 函数名称作用描述current_date()当前日期current_time()当前时间current_timestamp()当前时间戳date(datetime)返回datetime参数的日期部分date_add(date,interval d_value_type)在date中添加…...

【C++杂货铺】探索string的底层实现

文章目录 一、成员变量二、成员函数2.1 默认构造函数2.2 拷贝构造函数2.3 operator2.4 c_str()2.5 size()2.6 operator[ ]2.7 iterator2.8 reserve2.9 resize2.10 push_back2.11 append2.12 operator2.13 insert2.14 erase2.15 find2.16 substr2.17 operator<<2.18 opera…...

c++ day1

定义一个命名空间Myspace&#xff0c;包含以下函数&#xff1a;将一个字符串中的所有单词进行反转&#xff0c;并输出反转后的结果。例如&#xff0c;输入字符串为"Hello World"&#xff0c;输出结果为"olleH dlroW"&#xff0c;并在主函数内测试该函数。 …...

变动的Python爬虫实现

在电商时代&#xff0c;了解商品价格的变动对于购物者和卖家来说都非常重要。本文将分享一种基于Python的实时监控电商平台商品价格变动的爬虫实现方法。通过本文的解决方案和代码示例&#xff0c;您将能够轻松监控商品价格&#xff0c;并及时做出决策。 一、了解需求和目标 在…...

mybatis-plus--配置-(sql)日志输出-自动填充-分页-多数据源-逻辑删除

写在前面&#xff1a; 本文主要介绍mybatis-plus的配置&#xff0c;以后在有的时候在补充。欢迎交流。 文章目录 日志输出自动填充分页全局字段配置多数据源 日志输出 调试的时候需要看执行的sql&#xff0c;这时候就很需要日志来记录查看了。 mybatis-plus的日志配置在yml…...

数据API服务管理功能:解放数据潜力,提升业务效率

数据API服务的重要性 在数字化时代&#xff0c;数据被认为是企业的重要资产。数据API服务的管理功能能够有效帮助企业实现数据的整合和利用。通过合理的数据API服务管理&#xff0c;企业可以更好地解放数据潜力&#xff0c;提升业务效率。 ​ 解放数据潜力 数据API服务管理功…...

云南森林火灾vr消防模拟安全演练系统训练消防员火灾和事故的适应和应对能力

据统计,每一场破坏性地震发生后,会引发次生的灾害,而火灾是其中之一。导致火灾的原因,推测是地震时使供电线路短路,引燃易燃物,火灾就随即发生。所以,在日常生活中,定期的消防演练还是非常必要的, VR消防&#xff0c;是VR公司深圳华锐视点利用VR虚拟现实技术&#xff0c;将VR和…...

(6)(6.2) 任务命令

文章目录 前言 6.2.1 概述 6.2.2 导航命令 6.2.3 条件命令 6.2.4 DO命令 前言 本文介绍了 Copter、Plane 和 Rover 切换到自动模式时支持的任务指令。 &#xff01;Warning 这是一项正在进行中的工作&#xff0c;尚未经过全面审核。有关 Copter 的更佳列表&#xff0c;请…...

【consul】

consul 一、什么是服务注册与发现1.11.2 二、 什么是consul2.1定义2.2特性2.2.1服务注册与发现&#xff1a;2.2.2健康检查&#xff1a;2.2.3Key/Value存储&#xff1a; 三、consul部署-datacenter &#xff1a;指定数据中心名称&#xff0c;默认是dc1。consul &#xff1a;指定…...

Electron环境搭建

Electron是一个优秀的开源框架&#xff0c;用于构建跨平台的桌面应用程序。它基于Chromium和Node.js&#xff0c;使得开发者可以使用Web技术&#xff08;HTML、CSS和JavaScript&#xff09;来构建可在Windows、macOS和Linux等多个操作系统上运行的应用程序。本文将介绍如何搭建…...

MinIO线上扩容实战

硬件投入肯定是随着业务的增长而增长&#xff0c;这就要求中间件平台必须提供水平伸缩机制&#xff0c;MinIO对象存储服务也不例外&#xff0c;本文就详细介绍MinIO的扩容。 Minio支持通过增加新的Server Pool来扩容老的集群。每个Server Pool都是一个相对独立的故障域&#x…...

【微服务】微服务的概论

微服务&#xff1a;构建面向为了解决这个问题&#xff0c;微服务架构应运而生。本文将向您介绍微服务的概念、优势、实现原理以及应用场景&#xff0c;带您领略微服务在构建面向未来的高效应用中的魅力。 一、微服务的概念和优势 微服务是一种将应用拆分为一系列小型、独立服…...

基于Jenkins自动打包并部署docker环境

目录 1、安装docker-ce 2、阿里云镜像加速器 3、构建tomcat 基础镜像 4、构建一个Maven项目 实验环境 操作系统 IP地址 主机名 角色 CentOS7.5 192.168.200.111 git git服务器 CentOS7.5 192.168.200.112 Jenkins git客户端 jenkins服务器 CentOS7.5 192.168…...

jvm 运行时数据区

Java虚拟机定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁。另外一些则是与线程一一对应的,这些与线程对应的数据区域会随着线程开始和结束而创建和销毁 1.1程序计数器 程序计数器也叫pc寄存器 可以看作是当前线程…...

Jobs Portal求职招聘系统源码v3.5版本

Jobs Portal求职招聘系统 是为求职者和公司发布职位而开发的交互式求职招聘源码。它使求职者能够发布简历、搜索工作、查看个人工作列表。 它将提供各种公司在网站上放置他们的职位空缺资料&#xff0c;并且还可以选择搜索候选人简历。 除此之外&#xff0c;还有一个管理模块供…...

Android kotlin系列讲解(入门篇)使用Intent在Activity之间穿梭

<<返回总目录 上一篇:Android kotlin系列讲解(入门篇)Activity的理解与基本用法 文章目录 1、使用显式Intent2、使用隐式Intent3、更多隐式Intent的用法4、向下一个Activity传递数据5、返回数据给上一个Activity1、使用显式Intent 你应该已经对创建Activity的流程比较…...

做网站引流做什么类型的网站最好/百度搜索量怎么查

1、明确需求 实战工作中经常会请求各种各样的接口&#xff0c;例如 •微信网页授权接口 • 高德周边检索接口 •发现&#xff1a;下图是根据接口文档开发后的代码&#xff0c;发现代码可读性差&#xff08;ps. 参数的作用不详&#xff09; • 解决&#xff1a;通过http_buil…...

邯郸网站网站建设/东莞seo网络优化

localStorage 生命周期是永久的 这意味着除非用户显示在浏览器提供的UI上清除localStorage信息&#xff0c;否则这些信息将永远存在。sessionStorage 生命周期为当前窗口或标签页&#xff0c;一旦窗口或标签页被永久关闭了&#xff0c;那么所有通过sessionStorage存储的数据也…...

wordpress facebook login/谷歌外链工具

两个节点&#xff0c;都可以更新数据&#xff0c;并且互为主从&#xff0c;容易产生的问题&#xff1a;数据不一致&#xff1b;因此慎用&#xff0c;考虑要点&#xff1a;自动增长id&#xff0c;配置一个节点使用奇数id 主主复制的配置步骤&#xff1a; (1) 各节点使用一个惟一…...

drupal 网站实例/上海百度竞价托管

卡布列克数(Kaprekar number)是具有以下性质的数&#xff1a;对于某个正整数X {\displaystyle X}在n进位下存在正整数 A, B 及 m&#xff0c;且0 < B < b n {\displaystyle 0X 2 A n m B {\displaystyle X^{2}An^{m}B}X A B {\displaystyle XAB}简单的说&#xff0c;…...

济南外贸网站建设公司排名/在线识图

计算机网络课程设计某大学校园网设计_1摘要当今世界&#xff0c;各种先进的科学技术飞速发展&#xff0c;给人们的生活带来了深远的影响&#xff0c;它极大地改善着我们的生活方式。在以计算机技术为代表的信息科技的发展更是日新月异&#xff0c;从各个方面影响和改变着我们的…...

.net网站制作/廊坊网站建设公司

1LRC电路 有一个LRC电路连接电容电感如上&#xff0c;电压VV0Cos(ωt)VV_{0}Cos(\omega t)VV0​Cos(ωt) 以此建立方程 VCIR−V0Cos(ωt)−LdIdtV_{C}IR-V_{0}Cos(\omega t)-L\frac{dI}{dt} VC​IR−V0​Cos(ωt)−LdtdI​ IdQdtI\frac{dQ}{dt} IdtdQ​ VCQCV_{C}\frac{Q}{C} V…...