linux_c++GDB环境搭建(一)
温故而知新,从事C++ 好久了,今天起写点,从环境搭建开始
1:环境
ubuntu22.04 LTS download:https://releases.ubuntu.com/
各版本里面都有,自行选择下载
vmworkstation 17 pro
安装 就不说了,网上一堆教程,这里直接跳过
2:更换国内源
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
sudo vim /etc/apt/sources.list
内容如下,这里用阿里的(也可以用其他的,网上教程一堆)
deb http://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ jammy-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ jammy-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ jammy-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ jammy-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ jammy-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ jammy-backports main restricted universe multiverse
2:安装gcc,g++
update-alternatives管理GCC版本
1>更新
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
2>安装gcc/g++ * (这里也13为例,可以安装多个版本)
sudo apt-get install gcc-13
sudo apt-get install g+±13
3> 设置 数字越大优先级越高
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 130
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g+±13 130
4> 不同版本切换
sudo update-alternatives --config gcc
sudo update-alternatives --config g++
eg:
sudo update-alternatives --config gcc
There are 2 choices for the alternative gcc (providing /usr/bin/gcc).
Selection Path Priority Status
- 0 /usr/bin/gcc-13 130 auto mode 自动模式
1 /usr/bin/gcc-9 90 manual mode 手动模式
2 /usr/bin/gcc-13 130 manual mode 手动模式
3:core开启
1>ulimit -c
ulimit -c 可以查看是否打开此选项,若为0则为关闭;
ulimit -c 0可手动关闭
ulimit -c 1000 为设置core文件大小最大为1000k
ulimit -c unlimited 设置core文件大小为不限制大小
(1)临时 有效 Terminal 上 执行 ulimit -c 大小(KB)
(2)永久有效
/etc/security/limits.conf 修改
eg: unlimited 可以替换为 大小(KB)
@root soft core unlimited
@root hard core unlimited
其他方式修改
在/etc/profile 中增加一行 ulimit -c unlimited
2>关掉apport服务 ,不然不会生产core文件 (apport错误收集系统)
$ cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g – %E
关闭 apport.service 服务
sudo service apport stop
3>修改core dump文件路径
方法1-临时修改
修改 /proc/sys/kernel/core_pattern 文件,但/proc目录本身是动态加载的,每次系统重启都会重新加载,因此这种方法只能作为临时修改。
echo ‘/var/log/%e.core.%p’ > /proc/sys/kernel/core_pattern
方法2:永久修改
使用 sysctl -w name=value 命令。
sysctl -w kernel.core_pattern=/var/log/%e.core.%p
%% 单个%字符
%p 所dump进程的进程ID
%u 所dump进程的实际用户ID
%g 所dump进程的实际组ID
%s 导致本次core dump的信号
%t core dump的时间 (由1970年1月1日计起的秒数)
%h 主机名
%e 程序文件名
4:设置core文件的名称和文件路径
默认生成路径:输入可执行文件运行命令的同一路径下
默认生成名字:默认命名为core。新的core文件会覆盖旧的core文件
a.设置pid作为文件扩展名
1:添加pid作为扩展名,生成的core文件名称为core.pid
0:不添加pid作为扩展名,生成的core文件名称为core
修改 /proc/sys/kernel/core_uses_pid 文件内容为: 1
修改文件命令: echo "1" > /proc/sys/kernel/core_uses_pid
或者
sysctl -w kernel.core_uses_pid=1 kernel.core_uses_pid = 1
b. 控制core文件保存位置和文件名格式
修改文件命令: echo "/corefile/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
或者:
sysctl -w kernel.core_pattern=/corefile/core-%e-%p-%t kernel.core_pattern = /corefile/core-%e-%p-%t
可以将core文件统一生成到/corefile目录下,产生的文件名为core-命令名-pid-时间戳
以下是参数列表:
%p - insert pid into filename 添加pid(进程id)
%u - insert current uid into filename 添加当前uid(用户id)
%g - insert current gid into filename 添加当前gid(用户组id)
%s - insert signal that caused the coredump into the filename 添加导致产生core的信号
%t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间
%h - insert hostname where the coredump happened into filename 添加主机名
%e - insert coredumping executable name into filename 添加导致产生core的命令名
5:测试是否能生成core文件
编译时加 -g
向目标进程发送信号产生coredump
kill -s SIGSEGV pid
或
直接 写个dump代码
eg:
#include <iostream>
using namespace std;
int main(){
char *p = NULL;
cout<<"b"<<endl;
cout<<"c"<<endl;
p[0] ='C';
cout<<"finish"<<endl;
return 0;
}
4:gdb命令
1.启动程序和执行控制:
run: 启动正在调试的程序。
continue (c): 继续执行程序,直到遇到下一个断点或者程序结束。
next (n): 执行程序的下一行,但是如果有函数调用,则会一次性执行完函数内部所有语句。
step (s): 执行程序的下一行,如果是函数调用,则进入函数内部。
finish: 执行完当前函数的剩余部分,并返回到调用该函数的地方。
2.断点:
break (b) <line>: 在指定行设置断点。
break <function>: 在指定函数设置断点。
delete <breakpoint number>: 删除指定编号的断点。
clear <line>: 清除指定行的断点。
info breakpoints: 显示当前所有断点的信息。
3.查看变量和表达式:
print (p) <variable>: 打印变量的值。
display <expression>: 持续打印表达式的值,每次停止时都会显示。
info locals: 显示当前作用域内的所有局部变量。
info args: 显示当前函数的参数列表和值。
info breakpoints: 显示当前所有断点的信息。
4.堆栈和调用信息:
backtrace (bt): 显示当前的函数调用堆栈。
frame (f) <number>: 切换到指定堆栈帧。
up (u): 在堆栈中向上移动一帧。
down (d): 在堆栈中向下移动一帧。
5.控制程序执行:
kill: 终止正在调试的程序。
quit (q): 退出 GDB 调试器。
6.设置和配置:
set <variable> <value>: 设置 GDB 的变量或选项。
show <variable>: 显示当前设置的变量或选项。
7.其他常用命令:
help (h): 显示 GDB 帮助信息,可以查看特定命令的用法。
info <info-type>: 显示关于程序状态的特定信息,如 info breakpoints、info registers 等。
这些命令覆盖了常见的调试需求,可以帮助你在 GDB 中有效地分析和调试程序
当涉及更复杂的调试场景或者需要更精细控制的时候,GDB 提供了一些高级的操作指令,可以帮助进一步深入调试程序。以下是一些高级操作指令的示例:
1.条件断点:
break <location> if <condition>: 在满足特定条件时设置断点。例如:
Copy Code
(gdb) break main if argc > 1
这将在 main 函数入口处,且 argc 大于 1 时设置断点。
2.观察点(Watchpoints):
watch <expression>: 设置当表达式的值发生变化时停止程序执行的观察点。例如:
Copy Code
(gdb) watch x
这将在变量 x 的值发生变化时停止程序执行。
3.信号处理:
handle <signal> <action>: 指定 GDB 如何处理特定信号。例如:
Copy Code
(gdb) handle SIGINT nostop
这将使 GDB 在接收到 SIGINT 信号(如 Ctrl+C)时不暂停程序执行。
4.改变程序状态:
set variable <variable> <value>: 修改程序中的变量的值。例如:
Copy Code
(gdb) set variable x = 10
这将将变量 x 的值设置为 10。
5.查看寄存器:
info registers: 显示当前所有寄存器的值。
print $register: 打印特定寄存器的值,如 $eax, $ebx 等。
线程和并发调试:
info threads: 显示当前所有线程的信息。
thread <thread-id>: 切换到指定的线程。
thread apply <thread-id-list> <command>: 对指定的多个线程执行相同的 GDB 命令。
6.反汇编和内存查看:
disassemble <function>: 反汇编指定函数的代码。
x/<n><format> <address/expression>: 以特定格式查看内存内容。例如:
Copy Code
(gdb) x/4xw &variable
这将以 4 个 32 位字的十六进制格式查看 variable 的内存内容。
7.宏和脚本:
define/end: 定义和执行简单的 GDB 宏。例如:
Copy Code
(gdb) define printargs
> info args
> end
这将定义一个 printargs 宏,执行时会显示当前函数的参数。
8.远程调试:
target remote <hostname:port>: 连接到远程调试目标。
Python 脚本支持:
GDB 支持 Python 扩展,可以编写更复杂的脚本来增强调试功能。
这些高级操作指令可以帮助你更精确地控制和分析程序的执行过程,在处理复杂调试任务时尤其有用。随着对 GDB 更深入的了解和经验积累,你可以根据具体的调试需求利用这些功能来更有效地解决问题。
9.其他高级功能
使用条件断点 在特定条件下触发断点。
监视点和表达式 使用 watch 命令监视变量,或者使用 display 命令在每次停止时显示表达式的值。
调试优化 使用 GDB 的 -Og 选项进行与优化代码的调试。
通过这些高级功能,你可以更有效地调试复杂的程序,包括多线程、动态内存分配和复杂的数据结构。每个功能都能帮助你深入理解程序的运行状态和代码执行路径。
5:如果觉得有用,麻烦点个赞,加个收藏