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的主要作用包括以下几个方面:
- 检查程序状态:GDB可以帮助程序员在程序运行时检查程序的状态,包括变量的值、函数的调用栈、程序的执行流程等。
- 查找程序错误和问题:GDB可以帮助程序员更快地找到程序中的错误和问题,提高程序的质量和稳定性。
- 设置断点:GDB可以设置断点,让程序在特定的位置停下来,以便程序员检查程序的状态。
- 提供调试工具:GDB还提供了一些调试工具,如单步执行、查看内存、查看寄存器等,帮助程序员更好地理解程序的行为。
总之,GDB是一种非常强大的调试工具,可以帮助程序员更快地找到程序中的错误和问题,提高程序的质量和稳定性。
1.2 为什么要学习GDB
学习GDB可以帮助程序员更好地调试程序,找到程序中的错误和问题,提高程序的质量和稳定性。
在开发大型软件时,程序中可能存在许多错误和问题,这些问题可能会导致程序崩溃或者出现不可预期的行为。
使用GDB可以帮助程序员更快地找到这些问题,并且提供一些调试工具来帮助程序员更好地理解程序的行为。
此外,学习GDB还可以提高程序员的调试能力,让他们更加熟练地使用调试工具,提高工作效率。
因此,学习GDB是非常有必要的。
1.3 主要内容
- linux C/C++开发调试环境准备;
- GDB调试基本功能介绍;
- 调试执行;
- 断点管理;
- 线程管理;
- 调用栈管理;
- 查看修改变量;
- 其它基本功能;
- 多线程死锁调试;
- 动态库调试;
- 内存检查
- 内存泄漏;
- 堆栈溢出;
- 删除后继续使用;
- 远程调试;
- Core dump调试分析;
- 发行版调试。
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。
- r是run的缩写,
- 命令中的-q是用于关闭启动时的提示信息。
1.2 附加到进程
-
什么是附加到进程调试
附加到进程调试是一种调试技术,它允许开发人员在程序运行时观察和分析程序的内部状态。
通常,在调试过程中,开发人员会在代码中设置断点,以便在程序执行到特定位置时停止并检查其状态。但是,有时候问题可能只在程序运行的特定环境中出现,或者只在特定条件下才能复现。这时,附加到进程调试就非常有用了。
附加到进程调试的过程通常包括以下几个步骤:
- 打开调试器:首先,开发人员需要打开一个调试器,例如Visual Studio、GDB或LLDB等。调试器是一个用于观察和控制程序执行的工具。
- 选择进程:开发人员需要选择要附加调试的进程。这可以是正在运行的本地程序,也可以是远程计算机上的程序。
- 设置断点:开发人员可以在代码中设置断点,以便在程序执行到特定位置时停止。断点可以设置在函数调用、条件语句、循环等位置。
- 开始调试:一旦选择了进程并设置了断点,开发人员就可以开始调试了。调试器会监视程序的执行,并在断点处停止程序。
- 观察和分析:当程序停止在断点处时,开发人员可以观察和分析程序的内部状态,例如变量的值、函数的调用堆栈等。这有助于理解程序的行为和找出问题所在。
- 继续执行:在观察和分析完程序的内部状态后,开发人员可以选择继续执行程序,直到下一个断点或程序结束。
附加到进程调试是一种强大的调试技术,可以帮助开发人员快速定位和解决程序中的问题。它在软件开发和故障排除过程中非常常见和重要。
-
下面三条命令的主要区别在于语法的不同,但它们的功能是相同的。你可以使用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; }
-
演示如下
- 使用命令
g++ test2.cpp -g
编译代码,加上-g
生成包含调试详细的可执行程序; - 运行可执行程序;
- 使用命令
cat -n test2.cpp
查看源代码; - 使用命令
ps -aux | grep a.out
查看名称为a.out的进程的pid号; - 进程的pid号;
- 使用命令
sudo gdb -q -p 9834
将gdb附加到pid号为9834的进程进行调试,需要使用超级用户权限; - 使用命令
b test2.cpp:8
在test2.cpp文件的第8行打一个断点; - 继续执行gdb,c命令是continue的缩写,用于继续执行程序直到下一个断点或程序结束;
- 单步执行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 设置断点
-
设置断点命令
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
处设置一个断点;
- 行号断点:使用
tbreak
:命令用于设置临时断点,缩写为tb
。与break命令不同,临时断点只会在程序执行到该断点时触发一次,然后自动被删除。您可以使用tbreak命令后跟函数或行号来设置临时断点。rbreak
:设置正则表达式断点,缩写为rb
;- 语法
rbreak [regexp]
,其中,regexp是一个正则表达式,用于匹配要设置断点的函数名。rbreak命令会在所有可执行文件中搜索匹配的函数名,并在每个匹配的函数入口处设置断点; - 设置所有函数名以"foo"开头的断点: rbreak ^foo
- 设置所有函数名以"bar"结尾的断点: rbreak bar$
- 设置所有函数名中包含"baz"的断点: rbreak baz
- 语法
catch
:catch命令用于设置异常断点。- 异常断点会在程序抛出异常时触发。您可以使用catch命令后跟异常类型来设置异常断点;
- 语法
catch [exception] [command]
; - exception:是要捕获的异常类型,可以是以下几种:
- throw:捕获由C++程序中的throw语句引发的异常。
- catch:捕获由C++程序中的catch语句处理的异常。
- exec:捕获由被调试程序中的exec调用引发的异常。
- fork:捕获由被调试程序中的fork调用引发的异常。
- vfork:捕获由被调试程序中的vfork调用引发的异常。
- syscall:捕获由被调试程序中的系统调用引发的异常。
- command:是在捕获到异常时要执行的命令。如果省略command,则gdb会在捕获到异常时停止程序的执行并显示相关信息。
trace
:用于设置跟踪点。- 跟踪点是一种特殊的断点,它可以在程序执行到指定的函数或行号时触发,并显示函数的参数和返回值。
- 跟踪点可以帮助开发人员更详细地了解程序的执行过程,以便更好地调试和分析代码。
-
演示
1.2 管理断点
-
gdb断点管理常用命令
-
delete
:删除断点。会从断点列表中删除指定的断点,但不会清除程序中的断点位置。如果再次运行程序,断点仍然会被触发。-
缩写为
d
; -
删除所有断点:使用
delete
命令后不加任何参数,即可删除所有已设置的断点。 -
删除指定编号的断点:每个断点都有一个唯一的编号,可以使用
delete
命令后加上断点编号来删除指定的断点。例如delete 1
。 -
删除所有在指定函数中设置的断点:可以使用
delete
命令后加上函数名来删除所有在该函数中设置的断点。例如delete function_name
。 -
删除所有在指定文件中设置的断点:可以使用
delete
命令后加上文件名来删除所有在该文件中设置的断点。例如:delete file_name
。 -
删除所有在指定行号处设置的断点:可以使用
delete
命令后加上行号来删除所有在该行号处设置的断点。例如delete line_number
。 -
需要注意的是,删除断点时需要确保当前正在调试的程序处于暂停状态,否则删除操作可能无效。可以使用
info breakpoints
命令来查看当前已设置的断点,并获取它们的编号以及其他相关信息。
-
-
clear
:清除断点。会从程序中清除指定的断点位置,这意味着即使再次运行程序,断点也不会被触发。- 清除所有断点:使用
clear
命令后不跟任何参数,可以清除所有已设置的断点。 - 清除指定行号的断点:使用clear命令后跟上要清除断点的源文件名和行号,可以清除指定行号的断点。例如,
clear main.cpp:10
可以清除main.cp文件中第10行的断点。 - 清除指定函数的断点:使用clear命令后跟上要清除断点的函数名,可以清除指定函数的断点。例如
clear my_function
可以清除名为my_function的函数的断点。 - 清除指定源文件的断点:使用clear命令后跟上要清除断点的源文件名,可以清除指定源文件的所有断点。例如,
clear main.cpp
可以清除main.cp文件中的所有断点。
- 清除所有断点:使用
-
disable
:禁用断点、观察点或线程。-
语法:
disable [breakpoint|watchpoint|thread] <编号>
;breakpoint
表示断点;watchpoint
表示观察点;thread
表示线程;<编号>
是要禁用的断点、观察点或线程的编号。
-
可以使用
disable
命令后跟断点号来禁用特定的断点,例如disable 1
。
-
-
enable
:用于启用断点。- 可以使用
enable
命令后跟断点号来启用特定的断点,例如enable 1
。
- 可以使用
-
info breakpoints
:显示当前设置的所有断点。- 缩写为
i b
; - 使用
info breakpoints
命令可以查看当前设置的所有断点的详细信息,包括断点号、断点类型、断点位置等。
- 缩写为
-
-
演示
5、gdb的图形化界面功能
gdb中的tui是指Text User Interface,它是gdb的一个可选功能,用于在终端中以图形化的方式显示源代码、汇编代码和调试信息。
tui提供了一个类似于文本编辑器的界面,可以在调试过程中更方便地查看和操作代码。
使用tui可以在终端中同时显示源代码和调试信息,以及当前执行的代码行。
它可以帮助开发人员更直观地理解代码的执行流程,快速定位问题。
启动tui功能的方式:
- 启动gdb时使用命令
gdb -tui 可执行程序
; - 在gdb命令行中输入命令
tui enable
; - 在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
缩写为win
。win_name
可以是src
、cmd
、asm
和regs
)。- 例如:
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; }
-
常用命令
info locals
:显示当前栈帧的局部变量的值。info args
:gdb将会显示出当前函数的参数列表及其对应的值。这些参数包括函数的形参名称以及实际传递给函数的值。info variables
:这个命令将显示当前作用域中所有变量的列表,包括全局变量。print variable_name
:这个命令将显示指定变量的值。(缩写为p)set print null-stop
:设置字符串的显示规则,显示字符串时遇见\0
就停止输出;set print pretty
:显示结构体,结构体换行输出;set print array on
:显示数组;p 变量名=value
:修改变量值为value;set var 变量名=value
:修改变量值为value;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; }
-
使用命令
backtrace
命令:显示当前的函数调用栈。可以在程序崩溃或中止时使用,用来追踪函数调用链以确定程序执行到哪里。缩写为bt
;up
和down
命令:在当前函数调用链中向上或向下切换。up
: 切换到调用当前函数的函数down
:切换回当前函数up n
:向上选择函数堆栈帧,其中n是层数down n
:切向下选择函数堆栈帧,其中n是层数
frame
命令:切换到指定的栈帧(Stack Frame)。- 先使用
backtrace
查看栈帧列表 - 在使用
frame 2
切换到第3个栈帧
- 先使用
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 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;} }
-
演示
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调试—入门用法(1) 文章目录 gdb调试---入门用法(1)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的性能曲线,这样最能直接观察HDD或者SSD的性能曲线。 如下这是一个针对HDD跑Fio读写的iostat监控log,下面介绍一下分别用shell 和Python3 写画iostat图的方法 1 shell脚本 环境:linux OS gnuplot工具 第一步 :解析iosta…...
设计模式(9)建造者模式
一、 1、概念:将一个复杂对象的构造与它的表示分离,使得同样的构造过程可以创建不同的表示。建造者模式主要用于创建一些复杂的对象,这些对象内部构建间的顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化;建造…...
PHP 创业感悟交流平台系统mysql数据库web结构apache计算机软件工程网页wamp
一、源码特点 PHP 创业感悟交流平台系统(含论坛)是一套完善的web设计系统,对理解php编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 源码下载: https://download.csdn.…...
工作流程引擎之flowable(集成springboot)
0、背景 现状:公司各部门业务系统有各自的工作流引擎,也有cross function的业务在不同系统或OA系统流转,没有统一的去规划布局统一的BPM解决方案,近期由于一个项目引发朝着整合统一的BPM方案,特了解一下市面上比较主流…...
leetcode54. 螺旋矩阵(java)
螺旋矩阵 题目描述解题 收缩法 上期经典算法 题目描述 难度 - 中等 原题链接 - leecode 54 螺旋矩阵 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 示例1: 输入: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 报错问题
场景: 1.Tabbar的内容是接口获取的 2. TabController? tabController;; 在onInit 方法中初始化tabbarController tabController TabController(initialIndex: 0, length: titleDataList.length, vsync: this); 这时候会报一个错误 Controllers l…...
Redis(缓存预热,缓存雪崩,缓存击穿,缓存穿透)
目录 一、缓存预热 二、缓存雪崩 三、缓存击穿 四、缓存穿透 一、缓存预热 开过车的都知道,冬天的时候启动我们的小汽车之后不要直接驾驶,先让车子发动机预热一段时间再启动。缓存预热是一样的道理。 缓存预热就是系统启动前,提前将相关的…...
UE4/5Niagara粒子特效学习(使用UE5.1,适合新手)
目录 创建空模板 创建粒子 粒子的基础属性 粒子的生命周期 颜色 大小设置 生成的位置 Skeletal Mesh Location的效果: Shape Location 添加速度 添加Noise力场 在生成中添加: 效果: 编辑 在更新中添加: 效果&…...
from moduleA import * 语句 和import moduleA 的区别
from moduleA import * 语句和import moduleA 的区别是: from moduleA import * 语句会将moduleA模块中的所有内容(函数、变量、类等)直接导入到当前模块的命名空间中,这样就可以直接使用它们,而不需要加上模块名的限…...
【leetcode 力扣刷题】交换链表中的节点
24. 两两交换链表中的节点 24. 两两交换链表中的节点两两节点分组,反转两个节点连接递归求解 24. 两两交换链表中的节点 题目链接:24. 两两交换链表中的节点 题目内容: 题目中强调不能修改节点内部值,是因为如果不加这个限制的话…...
学会Mybatis框架:让你的代码更具灵活性、可维护性、安全性和高效性【二.动态SQL】
🥳🥳Welcome Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于Mybatis的相关操作吧 目录 🥳🥳Welcome Huihuis Code World ! !🥳🥳 一.Mybatis动态SQL如何应用 1.需求 2.…...
Oracle 中 ROWNUM 使用问题记录
ROWNUM 使用问题记录(2023-08-17) Oracle 版本: 19.0.0.0.0 Enterprise现象:今天在项目遇到一个问题,测试人员反馈前一天能看到的数据今天看不到了 用表格举例,这是前一天看到的数据,有9、7、1 这几个数量信息 日期…...
MySQL数据库:内置函数
日期函数 规定:日期:年月日 时间:时分秒 函数名称作用描述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,包含以下函数:将一个字符串中的所有单词进行反转,并输出反转后的结果。例如,输入字符串为"Hello World",输出结果为"olleH dlroW",并在主函数内测试该函数。 …...
变动的Python爬虫实现
在电商时代,了解商品价格的变动对于购物者和卖家来说都非常重要。本文将分享一种基于Python的实时监控电商平台商品价格变动的爬虫实现方法。通过本文的解决方案和代码示例,您将能够轻松监控商品价格,并及时做出决策。 一、了解需求和目标 在…...
mybatis-plus--配置-(sql)日志输出-自动填充-分页-多数据源-逻辑删除
写在前面: 本文主要介绍mybatis-plus的配置,以后在有的时候在补充。欢迎交流。 文章目录 日志输出自动填充分页全局字段配置多数据源 日志输出 调试的时候需要看执行的sql,这时候就很需要日志来记录查看了。 mybatis-plus的日志配置在yml…...
数据API服务管理功能:解放数据潜力,提升业务效率
数据API服务的重要性 在数字化时代,数据被认为是企业的重要资产。数据API服务的管理功能能够有效帮助企业实现数据的整合和利用。通过合理的数据API服务管理,企业可以更好地解放数据潜力,提升业务效率。 解放数据潜力 数据API服务管理功…...
云南森林火灾vr消防模拟安全演练系统训练消防员火灾和事故的适应和应对能力
据统计,每一场破坏性地震发生后,会引发次生的灾害,而火灾是其中之一。导致火灾的原因,推测是地震时使供电线路短路,引燃易燃物,火灾就随即发生。所以,在日常生活中,定期的消防演练还是非常必要的, VR消防,是VR公司深圳华锐视点利用VR虚拟现实技术,将VR和…...
(6)(6.2) 任务命令
文章目录 前言 6.2.1 概述 6.2.2 导航命令 6.2.3 条件命令 6.2.4 DO命令 前言 本文介绍了 Copter、Plane 和 Rover 切换到自动模式时支持的任务指令。 !Warning 这是一项正在进行中的工作,尚未经过全面审核。有关 Copter 的更佳列表,请…...
【consul】
consul 一、什么是服务注册与发现1.11.2 二、 什么是consul2.1定义2.2特性2.2.1服务注册与发现:2.2.2健康检查:2.2.3Key/Value存储: 三、consul部署-datacenter :指定数据中心名称,默认是dc1。consul :指定…...
Electron环境搭建
Electron是一个优秀的开源框架,用于构建跨平台的桌面应用程序。它基于Chromium和Node.js,使得开发者可以使用Web技术(HTML、CSS和JavaScript)来构建可在Windows、macOS和Linux等多个操作系统上运行的应用程序。本文将介绍如何搭建…...
MinIO线上扩容实战
硬件投入肯定是随着业务的增长而增长,这就要求中间件平台必须提供水平伸缩机制,MinIO对象存储服务也不例外,本文就详细介绍MinIO的扩容。 Minio支持通过增加新的Server Pool来扩容老的集群。每个Server Pool都是一个相对独立的故障域&#x…...
【微服务】微服务的概论
微服务:构建面向为了解决这个问题,微服务架构应运而生。本文将向您介绍微服务的概念、优势、实现原理以及应用场景,带您领略微服务在构建面向未来的高效应用中的魅力。 一、微服务的概念和优势 微服务是一种将应用拆分为一系列小型、独立服…...
基于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求职招聘系统 是为求职者和公司发布职位而开发的交互式求职招聘源码。它使求职者能够发布简历、搜索工作、查看个人工作列表。 它将提供各种公司在网站上放置他们的职位空缺资料,并且还可以选择搜索候选人简历。 除此之外,还有一个管理模块供…...
Android kotlin系列讲解(入门篇)使用Intent在Activity之间穿梭
<<返回总目录 上一篇:Android kotlin系列讲解(入门篇)Activity的理解与基本用法 文章目录 1、使用显式Intent2、使用隐式Intent3、更多隐式Intent的用法4、向下一个Activity传递数据5、返回数据给上一个Activity1、使用显式Intent 你应该已经对创建Activity的流程比较…...
做网站引流做什么类型的网站最好/百度搜索量怎么查
1、明确需求 实战工作中经常会请求各种各样的接口,例如 •微信网页授权接口 • 高德周边检索接口 •发现:下图是根据接口文档开发后的代码,发现代码可读性差(ps. 参数的作用不详) • 解决:通过http_buil…...
邯郸网站网站建设/东莞seo网络优化
localStorage 生命周期是永久的 这意味着除非用户显示在浏览器提供的UI上清除localStorage信息,否则这些信息将永远存在。sessionStorage 生命周期为当前窗口或标签页,一旦窗口或标签页被永久关闭了,那么所有通过sessionStorage存储的数据也…...
wordpress facebook login/谷歌外链工具
两个节点,都可以更新数据,并且互为主从,容易产生的问题:数据不一致;因此慎用,考虑要点:自动增长id,配置一个节点使用奇数id 主主复制的配置步骤: (1) 各节点使用一个惟一…...
drupal 网站实例/上海百度竞价托管
卡布列克数(Kaprekar number)是具有以下性质的数:对于某个正整数X {\displaystyle X}在n进位下存在正整数 A, B 及 m,且0 < B < b n {\displaystyle 0X 2 A n m B {\displaystyle X^{2}An^{m}B}X A B {\displaystyle XAB}简单的说,…...
济南外贸网站建设公司排名/在线识图
计算机网络课程设计某大学校园网设计_1摘要当今世界,各种先进的科学技术飞速发展,给人们的生活带来了深远的影响,它极大地改善着我们的生活方式。在以计算机技术为代表的信息科技的发展更是日新月异,从各个方面影响和改变着我们的…...
.net网站制作/廊坊网站建设公司
1LRC电路 有一个LRC电路连接电容电感如上,电压VV0Cos(ωt)VV_{0}Cos(\omega t)VV0Cos(ωt) 以此建立方程 VCIR−V0Cos(ωt)−LdIdtV_{C}IR-V_{0}Cos(\omega t)-L\frac{dI}{dt} VCIR−V0Cos(ωt)−LdtdI IdQdtI\frac{dQ}{dt} IdtdQ VCQCV_{C}\frac{Q}{C} V…...