gdb调试

背景

调试linux程序一般有两种,一种是检查程序的日志输出,但如果问题与IO有关就不能通过日志获得调试信息了;

虽然gdb不常用且命令复杂,但却是不可或缺呀。

常用调试命令

分类 序号 命令 说明
运行 1 r run简写,运行程序,遇到断点暂停
2 c continue简写,继续执行直到下一个断点或程序结束
3 n next简写,单步跟踪,遇函数调用时不进入函数体
4 s step简写,单步进入,遇函数调用时进入函数体
5 until 如果进入循环体,until将继续执行直到跳出循环体
6 until +n 继续运行,到第n行暂停
7 finish 继续执行,直到当前函数返回,并打印函数返回时的堆栈地址及返回值等相关信息
8 call 函数(参数) 手动调用程序中的可见函数并传参
9 q quit简写,退出gdb
断点 10 b line/func if a > b 设置条件断点,断点位置是某文件的某行或某个函数入口处,如果条件成立则断点设置成功
11 delete n 删除第n个断点
12 disable n 暂停第n个断点
13 enable n 开启第n个断点
14 clear n 删除第n行上的断点
15 info b 查看断点设置情况
16 delete breakpoints 删除所有断点
查看源码 17 l 接着显示上次显示的后面的源码
18 l n 显示第n行附近的源码
19 l func 显示函数func附近的源码
打印表达式 20 print a 打印变量a的值
21 print ++a a加1后打印
22 print name 打印字符串name的值
23 priint func(n) 调用函数func并传参n,n可以是一个常量,也可以是一个程序中已定义的变量
24 display 表达式 常用于单步调试
25 watch 表达式 监视表达式,当表达式的值改变时运行暂停并打印监视点的值
26 whatis 查询变量或函数
27 info function 打印所有函数信息
28 info locals 显示当前堆栈的所有变量
查询运行状态 29 where/bt 查看当前堆栈列表
30 bt backtrace 显示当前调用堆栈
31 up/down 改变堆栈深度
32 set args 参数 设置运行参数
33 show args 查看运行参数
34 info program 查看运行状态
分割窗口 35 layout src 显示源码窗口
36 layout asm 显示反汇编窗口
37 layout regs 显示源码/反汇编和CPU寄存器窗口
38 layout split 显示源码和反汇编窗口
39 ctrl + l 清空窗口

 

调试流程总结

被调试的源码(来源:https://blog.csdn.net/haoel/article/details/2879

#include <iostream>
using namespace std;
 
int func(int n){
    int sum=0;
    for(int i=0; i<n; i++){
        sum+=i;
    }
    return sum;
}
 
int main(){
    long result = 0;
    for(int i=1; i<=100; i++){
        result += i;
    }
    cout<<"result[1-100] = "<<result<<endl;
    cout<<"result[1-250] = "<<func(250)<<endl;
}

编译

orejia@debian9:gdb$ g++ -g main.cc -o main

进入调试

orejia@debian9:gdb$ gdb main

 

命令执行顺序 阶段 命令 说明 备注
1 查看代码 l 打印源码 list简写,默认一次向下打印10行代码
2 <enter> 回车 回车重复执行上一次命令
3 设置断点 b main.cc:16 设置断点 break简写,在文件main.cc的第16行设置断点,如果程序只有一个文件可省略文件名
4 b main.cc:func 设置断点 在函数func入口处设置断点
  b 7 if sum > 4 设置条件断点 当 sum 大于 4时,程序在第7行暂停运行
5 info b 查看断点信息 info命令可打印与调试过程有关的信息,
6 运行调试 r 启动程序 代码开始执行,遇到断点暂停
7 n 单步执行 next简写
8 c 继续执行 continue简写,遇到下一一个断点将再次暂时
9 p i 查看变量 print i 打印变量i的当前值
10 bt 查看函数堆栈 breaktrace简写
11 finish 跳出当前函数 跳转到当前所在函数的被调用位置并继续执行,直到遇到下一个断点
12 退出调试 q 退出 退出gdb调试命令行

 

core文件

前期设置

解除core文件限制,将其添加至/etc/profile

ulimit -c unlimited

 

修改core存储位置(默认与可执行程序在同级目录,但因为不知名原因有时会找不到,因此建议设置一个固定位置)

/proc/sys/kernel/core/pattern代表core文件名,可以给它加上路径前缀以及可执行文件名、pid 、时间等后缀参数

sudo echo "/data/coredump/core-%e-%p-%t" > /proc/sys/kernel/core_pattern"

 

coredump可能原因:

  • 数组下标访问越界
  • 对常量区数据(如字符指针)进行写操作
  • 调用不安全的字符串操作函数(strcpy ctrcat等)
  • 局部数据量太大导致堆栈溢出
  • 使用空指针
  • 不规范的指针类型强制转换
  • 多线程访问共享数据时未加锁
  • 调用线程不安全函数

调试core文件

gdb ./test core

进入gdb后,执行bt显示堆栈

 

cmake使用gdb

SET(CMAKE_BUILD_TYPE "Debug") 
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
SET(CMAKE_C_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall -g -ggdb")

参考

官方英文文档:https://sourceware.org/gdb/

gdb常用命令:https://www.cnblogs.com/tangtangde12580/p/8045980.html

core文件详解:https://blog.csdn.net/wkd_007/article/details/79757289

gdb调试手册:https://blog.csdn.net/MOU_IT/article/details/88322477

posted on 2019-12-31 10:12  sermatec江  阅读(177)  评论(0编辑  收藏  举报