)
1.GDB用户态调试 /KGDB内核级调试使用GDB调试之前需要用-g选项编译程序这样可执行文件中才会包含符号表变量名、函数名、行号等信息g -g -o myprogram myprogram.cpp#步骤1启动GDB并设置断点delete是删断点 gdb ./test (gdb) break main # 在main函数入口打断点 (gdb) break 25 # 在源文件第25行打断点 (gdb) break func1 if x100 # 条件断点x等于100时才触发 (gdb) info breakpoints # 查看所有断点 # 步骤2运行程序 (gdb) run # 开始运行直到遇到断点 (gdb) run arg1 arg2 # 带命令行参数运行 (gdb) run input.txt # 重定向标准输入 # 步骤3当程序停在断点时单步执行与继续 (gdb) next # n单步执行不进入函数内部 (gdb) step # s单步执行会进入函数内部 (gdb) continue # c继续运行直到下一个断点或程序结束 (gdb) finish # 执行完当前函数并返回跳出函数 (gdb) until 30 # 运行到第30行用于跳出循环 # 步骤4查看状态 (gdb) print var # 打印变量var的值 (gdb) display var # 每次暂停时自动打印var的值 (gdb) info locals # 查看当前函数的所有局部变量 (gdb) info registers # 查看寄存器内容 (gdb) backtrace # bt查看函数调用栈崩溃时最常用 (gdb) list # 显示当前执行的源代码 (gdb) disas # 显示汇编代码 # 步骤5修改变量调试时临时改变行为 (gdb) set var x100 # 将变量x的值改为100 (gdb) call func2() # 手动调用函数func2举例段错误 (core dumped) SIGSEGV 信号错误码编号为 11。是由于程序尝试访问不存在的内存区域引发的。常见原因如下访问未初始化的指针空指针解引用ptr 未指向合法内存如未通过new 分配内存。数组越界访问释放后使用内存栈溢出。递归过深或局部变量占用过多栈空间。如何定位和解决运行 GDB执行程序查看堆栈信息(gdb) btBacktrace定位错误位置。利用gdb调试器跟踪调用栈使用gdb在程序崩溃时查看调用栈bt命令定位最后执行的函数检查该函数中是否有异常内存操作。若栈溢出调用栈会显示递归层数过深的函数若堆溢出可能指向new/malloc的异常调用。Core Dump文件是程序崩溃时的内存快照包含虚拟内存布局、寄存器状态、调用栈等信息。具体实现解析 Core Dump 中的 “程序头” 获取内存段信息代码段、数据段、堆、栈的地址范围从栈内存中提取调用栈函数返回地址映射到源代码的行号查看堆内存中的对象状态如通过print查看指针指向的内存内容判断是否有异常分配如超大对象。2. strace /ftrace / ltrace / ptrace/bpftrace 等或使用trace-cmd工具ptraceLinux 的系统调用接口API供调试/跟踪进程使用。strace基于 ptrace跟踪进程执行时的 系统调用 和 接收到的信号。是排查线上故障如文件打不开、权限错误、网络连接失败等的首选工具。ltrace跟踪用户态库函数动态链接的函数调用通常也基于 ptrace。ftrace内核内建的跟踪框架跟踪内核函数、上下文切换、IRQ、调度等需在内核/tracefs 中使用通常需 root。# -c 打印执行uptime时系统系统调用的时间、次数、出错次数和syscall strace -c uptime # -f 跟踪主进程及其所有子进程对 shell 脚本、多进程程序很重要 strace -f ./my_script.sh # 显示 ls 命令执行过程中所有的系统调用如 openat, read, write, close 等 strace ls /tmp # 把 strace 输出写入 debug.log避免干扰终端 strace -o debug.log nginx -t # 跟踪 PID 为 1234 的进程需有权限常用于诊断卡住的服务 strace -p 1234 # 只跟踪特定类型的系统调用如open、read、write、network等 strace -e traceopen,read,write curl https://example.comstrace 使用实践定位一次系统无法解析域名故障。无法访问外网域名提示Name or service not know。且已检查系统DNS配置文件/etc/resolv.conf正确排除DNS解析失败。域名解析通常跟系统读取文件相关因此只查看open file的过程。strace -e straceopen ping www.baidu.com如上图所示在系统调用过程中出现/usr/lib64/libnss_dns.so.2文件缺失则问题根因已确定为libnss_dns.so.2系统库文件缺失。libnss_dns.so.2文件由glibc-devel包产生因此重新安装该包即可。3.Valgrind - 内存泄漏检测 该释放的资源没有及时释放内存泄漏原因1.new/delete,new[]/delete[] 没有配对使用忘记释放动态分配的内存2.异常安全漏洞:异常改变了正常的执行流程导致释放代码被跳过3.当多个部分共享同一内存时释放责任不明确4.使用STL容器时存储了指针清空容器时指针指向的资源其实并没有释放造成内存泄漏5.智能指针循环引用问题方法使用完内存或资源后立即释放使用智能指针自动管理内存生命周期RAII 类封装资源。内存池能显著降低内存泄露的风险一次性从系统申请一大块内存后续的小对象分配不再调用 new/malloc而是从池中切分当整个池不再需要时一次性释放整块内存无需逐个 delete。valgrind安装完valgrind编译程序时一定加上-g gcc -g -o leak leak.c运行Valgrind检测valgrind --toolmemcheck --leak-checkfull --show-leak-kindsall ./leak--toolmemcheck使用内存检查工具默认工具--leak-checkfull详细显示内存泄漏信息--show-leak-kindsall显示所有类型的泄漏--track-originsyes 追踪未初始化值的来源--log-filevalgrind.log 将输出保存到文件--num-callers20 显示20层调用栈分析Valgrind输出结果解读关键信息比如definitely lost: 100 bytes明确的内存泄漏100字节by 0x10916D: main (leak.c:6)泄漏发生在 leak.c 文件的第6行就是 malloc(100) 那行1 allocs, 0 frees分配了1次释放了0次ASan另一个方法是ASanAddressSanitizer生成报告但不一定100%罗列出来问题。优点是比 Valgrind 快很多但泄漏检测不如 Valgrind 精确。需额外开启内存泄漏检测gcc -fsanitizeaddress -fno-omit-frame-pointer -g -o leak leak.c