GDB使用指南-3
调试运行环境
设置运行参数
1 |
|
在GDB中,可以通过set args
命令来设置运行参数
1 | (gdb) set args 参数1 参数2... |
改变工作目录
有时候我们需要在GDB跳转到别的文件目录中
1 | (gdb) cd /path/to/directory |
设置输入输出
假设我们有一个input.txt
和一个output.txt
作为程序的输入和输出文件,我们想让gdb在启动程序的时候进行重定向
1 | (gdb) run < input.txt > output.txt |
如果想保存整个程序的日志文件,我们需要set logging
命令
1 | (gdb) set logging file 文件名 |
线程调试
1 |
|
在线程调试中,如果要查看线程信息可以使用info thread
1 | (gdb) info thread |
如果需要切换到特定的线程里面
1 | (gdb) thread 线程号 |
其他关于线程的命令
break location thread thread-id
: 在指定线程上设置断点,仅当该特定线程执行时,它才会停止。set scheduler-locking
: 控制在调试过程中其他线程的行为。可以设置以下模式:off:不锁定,所有线程都可以运行。
on:锁定,只有当前线程可以运行。
step:只有一个线程在单步执行时才锁定其他线程。thread apply all command
: 对所有线程执行指定的命令。set follow-fork-mode
: 设置GDB在fork系统调用时如何跟踪进程。可以设置为 parent 或 child,分别表示跟踪父进程或子进程。set detach-on-fork
: 控制GDB在fork后是否保持调试父进程和子进程。catch thread
: 在任何线程创建或退出时设置断点。thread select
: 切换到已经停止的线程(例如,通过断点或者异常)。
检查堆栈
1 |
|
在调试过程中,堆栈是经常需要查看的
1 | (gdb) info stack |
跳转命令
在GDB中,我们可以使用jump命令(或简写为j)来实现跳转执行。例如,如果我们想从当前位置直接跳到第10行执行,可以使用以下命令:
1 | j 10 |
这样程序就会直接跳转到第10行开始执行,跳过中间所有的代码
跳转的限制
虽然跳转命令很强大,但它也有一些限制。例如,我们不能跳到一个没有被加载的函数或模块中,也不能跳到一个已经执行完毕的函数或模块中。
此外,频繁地使用跳转命令可能会导致程序状态的不一致,因此在使用时需要格外小心。
跳转应用的场景
- 绕过错误或崩溃:如果你在调试过程中遇到了一个会导致程序崩溃的代码块,并且希望跳过这部分代码继续调试程序的其他部分,可以使用jump命令。
- 重复执行代码:你可能想反复执行某段代码以观察问题,jump能够让你回到这段代码的起点。
- 测试代码路径:在多个分支或执行路径的代码中,你可能想强制执行某个特定的路径,即使它实际上在当前的程序状态下不会被执行。
- 跳过执行时间很长的函数:在调试时,你可能不想等待一个耗时的函数完成。你可以跳过这个函数的调用,直接跳到其后的代码执行。
信号命令
信号是一种通知机制,用于告知进程某些事件已经发生。经常被用于处理异常情况(例如程序错误、外部中断等),在GDB中我们可以通过信号命令来处理、模拟这些信号
生成和处理信号
在GDB中,我们可以使用signal命令来发送信号到正在调试的程序。例如,要发送一个SIGINT信号,我们可以使用以下命令:
1 | (gdb) signal SIGINT |
这是模拟用户按下Ctrl+C
的情况
查看和设置信号
要查看当前程序如何处理各种信号,可以使用info signals
1 | (gdb) info signals |
这将显示所有信号及其当前的处理方式。
如果我们想改变某个信号的处理方式,可以使用handle
命令。例如,要让程序在接收到SIGINT信号时停止并打印消息,我们可以使用:
1 | (gdb) handle SIGINT stop print |
这样,每当程序接收到SIGINT
信号时,它都会停止执行并在GDB中打印消息
运行SHELL命令
要想运行shell命令,我们只需要在命令前加上shell关键字即可
1 | (gdb) shell ... |
调试core文件
在软件开发过程中,程序可能会出现崩溃。为了更好地理解和解决这些崩溃,我们经常需要调试程序的core文件。core文件是程序崩溃时生成的,它包含了程序崩溃时的内存快照,帮助我们定位问题。
生成core文件
先放一份源文件,方便调试
1 |
|
当程序崩溃时,系统通常会生成一个core文件,要确保core文件被生成,需要设置ulimit
1 | ulimit -c unlimited |
使用GDB查看core文件
要使用GDB查看core文件,我们需要两个文件:崩溃的程序的可执行文件和core文件。使用以下命令启动GDB:
1 | gdb <executable-file> <core-file> |
这里可以使用coredumpctl来调用gdb
1 | # 启动最新的core文件 |
实时观察进程Crash信息
有时,我们可能希望实时观察进程的崩溃信息,而不是等待程序崩溃后再查看core文件。为此,我们可以使用strace工具跟踪系统调用和信号。
1 | strace -o output.txt <executable-file> |
这将在output.txt文件中记录所有的系统调用和信号,帮助我们实时观察进程的行为。