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

这篇具有很好参考价值的文章主要介绍了C++(Qt)软件调试---gdb调试入门用法(12)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

gdb调试—入门用法(1)

更多精彩内容
👉个人内容分类汇总 👈
👉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。

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

  • 命令中的-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命令来执行下一行代码,而不会进入函数调用。这个命令通常用于逐行执行程序,以便观察程序的执行流程。

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

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;
    }
    
  • 演示

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

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:用于设置跟踪点。
      • 跟踪点是一种特殊的断点,它可以在程序执行到指定的函数或行号时触发,并显示函数的参数和返回值。
      • 跟踪点可以帮助开发人员更详细地了解程序的执行过程,以便更好地调试和分析代码。
  • 演示

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

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命令可以查看当前设置的所有断点的详细信息,包括断点号、断点类型、断点位置等。
  • 演示

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

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窗口中可以实时看见。

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

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":修改字符串的值,需要注意内存越界;
  • 演示

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

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:需要设置的值。
  • 演示

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

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 第六个参数
  • 演示:没有调试符号时可以通过查看寄存器来进行调试。

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

  • 修改寄存器命令

  • 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这一行代码。

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

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 one
      
      class 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:设置每次显示的代码行数。
  • 演示

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

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的栈帧信息
  • 演示

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

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;
    }
    
    
  • 演示

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

13、gdb调试捕获点

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

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

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

    事件 说明
    catch assert Catch在引发时失败的Ada断言。
    catch catch 当程序捕获异常时触发捕获点。可以用来跟踪异常的捕获过程。
    catch exception Catch 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;
        }
    }
    
    
  • 演示

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

14、gdb生成core dump文件

  • 测试代码

  • 使用命令

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

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

15、gdb调试core dump

  • 测试代码

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

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

  • 演示

    C++(Qt)软件调试---gdb调试入门用法(12),# C++软件调试,c++,qt,gdb文章来源地址https://www.toymoban.com/news/detail-652322.html

到了这里,关于C++(Qt)软件调试---gdb调试入门用法(12)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Qt6 c++教程9测试&调试

    调试和测试是软件开发的重要组成部分。在本章中,你将学习如何调试 Qt 项目、不同的调试技术以及 Qt 支持的调试器。调试是发现错误或不希望出现的行为的根本原因并加以解决的过程。我们还将讨论使用Qt Test框架进行单元测试。Qt Test是基于Qt的应用程序和库的单元测试框

    2024年02月05日
    浏览(41)
  • 在linux中的GDB调试一些用法

    -g: 选项的作用是在可执行文件中加入源代码的信息 -Wall:尽量不影响程序行为的情况下选项打开所有warning program:为程序名 help:使用帮助 gdb:启动程序 quit:退出调试 set args num1 num2 …:设置程序中需要的参数(就是cin需要接收的值) show args:展示参数 list或者l :从默认位

    2024年02月05日
    浏览(46)
  • 【C++ QT项目2】——高仿安信可串口调试助手

      串口调试助手是一种串口通讯测试工具,它可以用于打开、关闭、配置串口,读写串口数据等常见的串口通信操作。 在嵌入式系统调试、模块测试、通讯协议分析等领域都具有广泛的应用。   串口助手通常提供GUI界面,让用户可以更加方便、直观地进行串口通讯测试

    2024年02月19日
    浏览(50)
  • 12-4_Qt 5.9 C++开发指南_创建和使用共享库

    除了静态库,Qt 还可以创建共享库, 也就是 Windows 平台上的动态链接库 。动态链接库项目编译后生成 DLL 文件,DLL 文件在 windows 平台上应用广泛。DLL 文件是在应用程序运行时加载的,不像静态库那样在编译期间就连编到应用程序里。若更新了 DLL 文件版本,只要接口未变,

    2024年02月14日
    浏览(53)
  • Linux - 还不懂 gdb 调试器?(调试软件)

    当前,我们可以使用 make/makefile 来程序化执行代码文件;可以使用 gcc/g++ 等编译器来编译代码;可以使用 vim 编辑器来编写代码;其实在 Linux 当中还有一个工具,可以实现调试工作,这个工具就是 -- gdb。 在了解调试器之前,你应该对代码的发布版本做一些了解: 我们在 VS

    2024年02月07日
    浏览(51)
  • QT C++入门学习(2) QT Creator写一个简单的上位机控制LED

    上位机:指的是可以直接发送操作指令的计算机或者单片机,一般提供用户操作交互界面并向用户展示反馈数据。 典型设备:电脑、平板、手机、面板、触摸屏 下位机:指的是与机器相连接的计算机或者单片机,一般用于接收和反馈上位机的指令,并根据指令控制机器执行

    2024年02月10日
    浏览(43)
  • 终端/Vscode + GDB调试C++程序

    CMakeLists中需要设置编译类型为Debug 下载gdb调试器 在终端使用gdb调试程序 然后进入(gdb)命令行 (gdb) set args … : 设置程序运行输入的参数 (gdb) break file_path:row_number : 设置断点位置 (gdb) run : 启动调试 (gdb) next : 下一步(不进入函数) (gdb) step : 下一步(进入函数) (gdb) continue : 继

    2024年02月04日
    浏览(37)
  • C++软件调试与异常排查从入门到精通系列文章汇总

    本文是 C++软件调试与异常排查从入门到精通系列教程 专栏的导航贴( 点击链接,跳转到专栏主页,欢迎订阅,持续更新… )。 📢 建议在阅读专栏文章时,使用本篇导航文章,本导航文章对专栏中的文章进行了分类与排序,读起来更有条理! 专栏介绍 :根据近几年C++软件

    2023年04月09日
    浏览(50)
  • Qt C++中调用python,并将软件打包发布,python含第三方依赖

    工作中遇到qt c++调用我的python 代码,并且想要一键打包,这里我根据参考的以及个人实践的结果来简单实现一下。 环境:windows系统,QT Creater 4.5, python 3.8(anaconda虚拟环境) 1.创建QT工程 中间省略3个步骤图。创建完成后,如图。 首先提示各位从python过来的同仁 ,QT中有时

    2024年01月20日
    浏览(49)
  • 【嵌入式Qt开发入门】在Ubuntu下编写C++

            在 Ubuntu 上面编写 C++,本文内容主要介绍在 Ubuntu 在终端窗口下使用 vi/vim 编辑一 个 C++源文件。通过编写最简单的示例“Hello,World!”。带领大家学习如何在 Ubuntu 终端下编辑和编译 C++。这里要求大家会在 Ubuntu 上使用 vi/vim,也就是要求大家有一点 Ubuntu 入门的基

    2024年02月11日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包