• 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

  • 相关阅读:
    Electron(3)调用第三方DLL
    Electron(1)概述
    Java SpringMVC(6)Mybatis-Plus
    Socket粘包问题的3种解决方案
    HTTP
    2020再见 2021你好
    再谈领域驱动设计
    使用Domain-Driven创建Hypermedia API
    使用函数式语言来建立领域模型--类型组合
    PHP安装扩展
  • 原文地址:https://www.cnblogs.com/orejia/p/12121974.html
Copyright © 2020-2023  润新知