一、GDB基础
1. 启动调试
gdb ./your_program # 启动调试
gdb --args ./prog arg1 # 带参数启动
gdb -p <pid> # 附加到正在运行的进程
2. 断点管理
b main # 在main函数设断点
b file.c:20 # 在file.c第20行设断点
b *0x4005a0 # 在内存地址设断点
info breakpoints # 查看所有断点
delete <num> # 删除断点
disable/enable <num> # 禁用/启用断点
3. 执行控制
run # 启动程序
continue (c) # 继续执行到下一个断点
next (n) # 单步执行(跳过函数)
step (s) # 单步进入函数
finish # 执行完当前函数并返回
until <line> # 执行到指定行
4. 查看变量和内存
print (p) x # 打印变量x
p *ptr@10 # 打印ptr指向的10个元素
p/x var # 十六进制格式打印
x/4xg 0x4000 # 查看内存:4个8字节十六进制值
info registers # 查看寄存器值
二、GDB进阶
1. 加载可执行程序和core dump文件
#include <stdio.h>int main(void) {int *p = NULL;printf("hello world\n");*p = 0;return 0;
}
例子程序访问了一个空指针,所以程序会crash并产生core dump文件。用gdb调试core dump文件,通常用这个命令形式:
gdb path/to/the/executable path/to/the/coredump
然后gdb会显示程序crash的位置。
2. 调试正在运行的进程
# 查找目标进程PID
ps aux | grep 程序名# 附加调试
gdb -p <PID>
(gdb) bt # 查看当前调用栈
(gdb) info threads # 查看所有线程
(gdb) thread <ID> # 切换线程
(gdb) frame <N> # 选择栈帧
(gdb) p variable # 打印变量
三、其他问题
1. 怎么debug,怎么看内存泄漏。
2. gdb 使用 -> 多线程程序切换到某线程栈帧 -> 如何查看寄存器值
# 在malloc/free处设断点
(gdb) break malloc
(gdb) break free# 记录所有内存分配
(gdb) set logging file mem.log
(gdb) set logging on# 运行后对比malloc/free调用次数
(gdb) info breakpoints
3. 怎么分析C++的core文件
启用core dump生成:
# 临时生效(当前会话)
ulimit -c unlimited # 解除大小限制
echo "/tmp/core.%e.%p" | sudo tee /proc/sys/kernel/core_pattern # 设置存储路径# 永久生效(需root)
echo "ulimit -c unlimited" >> /etc/profile
echo "/tmp/core.%e.%p" > /etc/sysctl.d/core.conf
sysctl -p /etc/sysctl.d/core.conf
g++ -g -O0 -rdynamic -o program program.cpp # 必须包含-g选项
加载core文件
gdb ./program /tmp/core.1234 # program是崩溃的可执行文件
查看崩溃位置:
(gdb) bt full # 显示完整调用栈(包含局部变量)
(gdb) frame N # 切换到指定栈帧(N为bt显示的编号)
(gdb) list # 显示崩溃点附近的源代码
4. GDB有哪些命令
1. 启动与退出
命令 | 说明 |
---|
gdb ./program | 启动GDB调试程序 |
run [args] | 运行程序(可带参数) |
quit | 退出GDB |
2. 断点管理
命令 | 说明 |
---|
break main | 在main函数设断点 |
break file.cpp:20 | 在指定文件的第20行设断点 |
break *0x4005a0 | 在内存地址设断点 |
info breakpoints | 查看所有断点 |
delete 2 | 删除编号为2的断点 |
disable/enable 1 | 禁用/启用编号1的断点 |
3. 执行控制
命令 | 说明 |
---|
next (n) | 单步执行(不进入函数) |
step (s) | 单步进入函数 |
continue (c) | 继续执行到下一个断点 |
finish | 执行完当前函数并暂停 |
until 30 | 运行到第30行 |
4. 变量与内存
命令 | 说明 |
---|
print x | 打印变量x的值 |
print *ptr@10 | 打印指针ptr指向的10个元素 |
x/4xw 0x4000 | 以16进制显示内存(4个word) |
info registers | 查看所有寄存器值 |
info locals | 显示当前栈帧的局部变量 |
5. 调用栈与线程
命令 | 说明 |
---|
backtrace (bt) | 查看调用栈 |
frame 2 | 切换到调用栈第2帧 |
info threads | 查看所有线程 |
thread 3 | 切换到线程3 |
6. 多进程/线程调试
命令 | 说明 |
---|
set follow-fork-mode child | 调试子进程 |
set scheduler-locking on | 锁定当前线程 |
thread apply all bt | 打印所有线程的调用栈 |
7. 实用辅助命令
命令 | 说明 |
---|
set logging on | 记录调试输出到文件 |
define hook-run | 定义启动时自动执行的命令 |
shell ls | 执行shell命令 |
help [command] | 查看命令帮助 |
5. gcc和g++的区别
特性 | gcc (GNU C Compiler) | g++ (GNU C++ Compiler) |
---|
默认语言标准 | C11 (可通过 -std= 指定其他版本) | C++17 (可通过 -std= 指定其他版本) |
链接阶段行为 | 默认不链接 C++ 标准库 | 自动链接 libstdc++ (C++ 标准库) |
文件扩展名处理 | 将 .c 文件视为 C 代码 | 将 .cpp /.cxx 视为 C++,.c 仍视为 C |
6. Linux下程序有问题,如何调试?(答GDB打开,打上Breakpoint进行调试)