使用 GDB 在 Linux 上进行 Debug
在 Linux 上使用 GDB 进行调试,主要分为以下几个步骤:
- 编译程序:
编译程序时需要加上 -g 选项,生成调试信息。例如:
gcc -g myprogram.c -o myprogram
- 启动 GDB:
可以使用以下两种方式启动 GDB:
- 直接调试程序:
gdb myprogram
- 调试已运行的程序:
gdb -p <pid>
其中 是要调试的程序的进程 ID。
- 设置断点:
在程序启动前,可以使用 break 命令设置断点。例如:
- 在 main 函数入口处设置断点:
(gdb) break main
- 在 myfunction 函数的第 10 行设置断点:
(gdb) break myfunction:10
- 在某个地址处设置断点:
(gdb) break *0x400500
- 运行程序:
使用 run 命令运行程序,程序会在断点处停止。
- 单步调试:
程序停止后,可以使用以下命令进行单步调试:
- next (或 n): 执行下一行代码,不进入函数内部。
- step (或 s): 执行下一行代码,如果遇到函数调用则进入函数内部。
- continue (或 c): 继续执行程序,直到遇到下一个断点或程序结束。
- finish (或 fin): 执行完当前函数并返回。
- 查看变量和内存:
可以使用以下命令查看变量和内存:
- print (或 p): 打印变量的值。例如:print i
- display (或 disp): 每次程序停止时都打印指定的变量值。例如:display i
- x/<n/f/u> : 以指定格式查看内存内容。
- n: 显示的单元个数
- f: 显示格式 (x 十六进制, d 十进制, u 无符号十进制, c 字符, s 字符串)
- u: 单元大小 (b 字节, h 半字, w 字, g 八字节)
- 其他常用命令:
- info breakpoints: 查看所有断点信息。
- delete <breakpoint_number>: 删除指定编号的断点。
- disable <breakpoint_number>: 禁用指定编号的断点。
- enable <breakpoint_number>: 启用指定编号的断点。
- backtrace (或 bt): 显示程序崩溃时的调用栈。
- info locals: 显示当前栈帧的局部变量。
- info registers: 显示寄存器的值。
- quit (或 q): 退出 GDB。
示例:
gcc -g myprogram.c -o myprogram
gdb myprogram
(gdb) break main
(gdb) run
(gdb) next
(gdb) print i
(gdb) continue
(gdb) quit
总结:
以上是使用 GDB 在 Linux 上进行 Debug 的基本步骤和常用命令。GDB 还有很多其他的功能,可以通过 help 命令查看帮助文档。
希望以上内容能够帮助入门 GDB 调试。
GDB 设置断点详解
在 GDB 中,断点是调试过程中非常重要的工具,它允许在程序执行到特定位置时暂停,以便检查程序状态、变量值等信息。
- 设置断点的方式:
GDB 提供了多种设置断点的方式,以下列举几种常用的方法:
- 按行号设置断点:
(gdb) break <line_number>
(gdb) b <line_number>
例如,在 main.c 文件的第 10 行设置断点:
(gdb) break main.c:10
- 按函数名设置断点:
(gdb) break <function_name>
(gdb) b <function_name>
例如,在 my_function 函数入口处设置断点:
(gdb) break my_function
- 按条件设置断点:
(gdb) break <line_number> if <condition>
(gdb) b <line_number> if <condition>
例如,在 main.c 文件的第 10 行设置断点,条件是变量 i 的值等于 10:
(gdb) break main.c:10 if i == 10
- 按地址设置断点:
(gdb) break *<address>
(gdb) b *<address>
例如,在地址 0x400500 处设置断点:
(gdb) break *0x400500
- 查看断点信息:
使用 info breakpoints (或 i b) 命令可以查看所有已设置的断点信息,包括断点编号、类型、位置、条件等。
- 管理断点:
- 删除断点:
(gdb) delete <breakpoint_number>
(gdb) d <breakpoint_number>
例如,删除编号为 1 的断点:
(gdb) delete 1
- 禁用断点:
(gdb) disable <breakpoint_number>
禁用断点后,程序执行到该断点位置时不会停止。
- 启用断点:
(gdb) enable <breakpoint_number>
启用断点后,程序执行到该断点位置时会停止。
- 其他断点相关命令:
- clear: 清除当前行或指定位置的断点。
- tbreak: 设置临时断点,程序在该断点停止一次后会自动删除。
- rbreak : 在所有匹配正则表达式的函数入口处设置断点。
- catch : 设置捕捉点,当指定事件发生时程序会停止,例如 catch throw 捕捉 C++ 异常抛出事件。
示例:
(gdb) break main
(gdb) run
Breakpoint 1, main () at main.c:10
10 int i = 0;
(gdb) print i
1 = 0
(gdb) continue
Continuing.
Breakpoint 1, main () at main.c:12
12 i++;
(gdb) print i
2 = 1
(gdb) disable 1
(gdb) continue
Continuing.
[Inferior 1 (process 18773) exited normally]
总结:
GDB 提供了丰富的断点设置和管理功能,熟练掌握这些功能可以帮助更高效地进行程序调试。
希望以上内容能够帮助更好地理解 GDB 断点设置。
在 GDB 中查看代码
GDB 提供了多种方式来查看程序代码,方便在调试过程中理解程序逻辑和定位问题。
- list 命令:
list 命令 (或 l) 是最常用的查看代码命令,它可以显示当前执行位置附近的代码。
- 显示当前执行位置附近的代码:
(gdb) list
- 显示指定行号附近的代码:
(gdb) list <line_number>
- 显示指定函数的代码:
(gdb) list <function_name>
- 显示指定文件中的代码:
(gdb) list <filename>:<line_number>
- 继续显示后续代码:
(gdb) list
每次执行 list 命令都会显示后续的代码行。
- 显示之前的代码:
(gdb) list -
- set listsize 命令:
可以使用 set listsize 命令设置每次 list 命令显示的代码行数。例如,设置每次显示 20 行代码:
(gdb) set listsize 20
- search 命令:
search 命令 (或 /) 可以在当前文件中搜索指定的字符串。例如,搜索字符串 “error”:
(gdb) search error
- forward-search 命令 和 reverse-search 命令:
forward-search 命令 (或 /) 和 reverse-search 命令 (或 ?) 分别向前和向后搜索指定的正则表达式。
- dir 命令:
dir 命令可以将源文件目录添加到 GDB 的搜索路径中,方便查看其他文件中的代码。例如,添加 /home/user/myproject/src 目录到搜索路径:
(gdb) dir /home/user/myproject/src
- info sources 命令:
info sources 命令可以显示 GDB 当前加载的源文件列表。
- frame 命令:
frame 命令可以切换到不同的栈帧,并显示对应栈帧的代码。例如,切换到栈帧 0:
(gdb) frame 0
示例:
(gdb) break main
(gdb) run
Breakpoint 1, main () at main.c:10
10 int i = 0;
(gdb) list
8 #include <stdio.h>
9
10 int main() {
11 int i = 0;
12 i++;
13 printf("i = %d\n", i);
14 return 0;
15 }
(gdb) list 15
10 int main() {
11 int i = 0;
12 i++;
13 printf("i = %d\n", i);
14 return 0;
15 }
(gdb)
实战:调试包含 3 个 cpp 文件的应用程序
创建一个简单的示例程序,包含以下三个文件:
main.cpp:
#include <iostream>
#include "calculator.h"
int main() {
Calculator calc;
int result = calc.add(5, 3);
std::cout << "Result: " << result << std::endl;
return 0;
}
calculator.h:
#ifndef CALCULATOR_H
#define CALCULATOR_H
class Calculator {
public:
int add(int a, int b);
int subtract(int a, int b);
};
#endif
calculator.cpp:
#include "calculator.h"
int Calculator::add(int a, int b) {
return a + b;
}
int Calculator::subtract(int a, int b) {
return a - b;
}
编译程序:
使用 -g 选项编译程序,生成调试信息:
g++ -g main.cpp calculator.cpp -o myapp
使用 GDB 调试:
- 启动 GDB:
gdb myapp
- 设置断点:
在 Calculator::add 函数入口处设置断点:
(gdb) break calculator.cpp:3
Breakpoint 1 at 0x...: file calculator.cpp, line 3.
- 运行程序:
(gdb) run
Starting program: /path/to/myapp
Breakpoint 1, Calculator::add (this=0x..., a=5, b=3) at calculator.cpp:3
3 return a + b;
程序会在断点处停止。
- 查看代码:
使用 list 命令查看当前代码:
(gdb) list
1 #include "calculator.h"
2
3 int Calculator::add(int a, int b) {
4 return a + b;
5 }
6
7 int Calculator::subtract(int a, int b) {
8 return a - b;
9 }
- 查看变量值:
使用 print 命令查看变量 a 和 b 的值:
(gdb) print a
1 = 5
(gdb) print b
2 = 3
- 单步执行:
使用 next 命令单步执行下一条语句:
(gdb) next
4 return a + b;
- 继续执行:
使用 continue 命令继续执行程序,直到下一个断点或程序结束:
(gdb) continue
Continuing.
Result: 8
[Inferior 1 (process 1234) exited normally]
其他常用命令:
- step: 单步执行,进入函数内部。
- backtrace: 查看函数调用栈。
- info breakpoints: 查看已设置的断点。
- delete: 删除断点。
3万+

被折叠的 条评论
为什么被折叠?



