• Linux友人帐之调试器--gdb的使用


    一、debug和realease版本的区别

    区别

    debug是给程序员用的版本,添加了调试信息,用于解决软件或程序中出现的问题,realease是发行给客户使用的版本,并未添加调试信息,只需要给客户提供优越的产品使用环境即可,至于是否能够debug调试,这是程序员才应该关心的主要问题。

    可以看到debug版本的字节大小是要大于realease版本的,这是因为其中添加了调试信息。

    通过指令可以读取可执行程序的二进制构成,显示出具体的二进制软件的内部所形成的特定格式。
    值得注意的是:每一个二进制程序不仅仅只是一堆二进制代码,他们内部都是有特定格式的,Linux中形成的可执行程序是elf格式。

     readelf命令

     readelf命令是一个可以读取ELF(Executable and Linkable Format)文件头部信息的Linux命令。ELF文件是一种可执行文件和共享库的标准格式,包含了代码段、数据段、符号表和动态链接信息等。通过readelf命令,用户可以查看这些信息,如ELF文件的类型、入口地址、节区信息、符号表、重定位信息、动态链接信息等。

    常用的readelf命令选项包括:

    • -a或--all:显示所有信息,默认选项;
    • -h或--file-header:显示文件头(包括ELF文件类型、入口地址等);
    • -S或--sections:显示节区信息;
    • -s或--symbols:显示符号表信息;
    • -r或--relocs:显示重定位信息;
    • -d或--dynamic:显示动态链接信息。

    下面就是debug中所添加的调试信息,而realease版本是没有这些调试信息的 

     

     

     二、 调试器gdb

    3.1gdb介绍

    gdb是GNU开源组织发布的一个用于Unix/Linux的程序调试工具。

    与其它调试器一样,gdb可以在程序中设置断点、查看变量值,跟踪程序执行的过程。

    利用调试器的这些功能可以方便地找出程序中存在的非语法错误。

    3.2环境配置

    安装

    编写一个用于测试的程序test.c 

    1. #include
    2. int get_sum(int n)
    3. {
    4. int sum = 0, i;
    5. for (i = 1; i <= n; i++)
    6. sum += i;
    7. return sum;
    8. }
    9. int main()
    10. {
    11. int j = 100, res;
    12. res = get_sum(j);
    13. printf("1+2+...+%d = %d\n", j, res);
    14. return 0;
    15. }

    编译并运行该程序

    gcc -g test.c -o test

    需要-g参数

    ./test

    几点注意:

    • 默认情况下,gdb无法进行对gcc现在发布的程序进行调试,因为gcc默认生成的软件是realease版本的,没有调试信息,无法被调试器gdb调试,并且gcc是默认动态链接的,如果想静态链接还需要加static选项,所有gcc是有两种默认行为的。
    • gcc编译时添加-g选项可以使得gcc发布的程序软件为debug版本,这样就可以通过gdb对程序进行调试

    3.3gdb的启动和退出

    启动:

    1. gdb [程序名]

    gdb test

    2. gdb --quiet

    (gdb)file test

    退出

    (gdb)quit

    3.4gdb常用命令

    help命令

     其他命令

    显示程序源代码list

    list: 输出从上次调用list命令开始向后的10行程序代码

    list -: 输出从上次调用list命令处向前10行代码

    list n: 输出n行附近的10行代码

    list [函数名]: 输出函数附近的10行代码

    list n1,n2: 显示第n1行到n2行的代码  

    搜索字符串

    forward/search [字符串]: 从当前位置向后查找指定的字符串所在的程序行,查找时不包括当前行,可以用list n,n将当前行设置为n

    reverse-search [字符串]: 从当前行向前查找第一个匹配的字符串

    执行程序

    在shell环境下使用gdb test,或在gdb环境下使用file test只是载入了程序,但是程序是没有运行的

    运行:

    (gdb)run

    3.5断点的设置和管理

    设置断点

    1 以行数设置断点

    格式: break n

    功能: 当程序运行到指定行时,会暂停执行,指定行的代码不执行

    例如:

    (gdb)break 15

    (gdb)run

    2 以函数设置断点

    格式: break [函数名]

    例如:

    (gdb)break get_sum

    (gdb)run

    3 以条件表达式设置断点

    格式: break [行号或函数名] if [条件]

    功能: 程序在运行过程中,满足设定条件时,程序在所设置处中断

    例如:

    (gdb)break 7 if i==99

    含义: 当程序执行到第7行时,判断条件i==99是否成立,若成立则中断

    4 以条件表达式变化设置断点

    格式: watch [条件表达式]

    功能: 程序在运行过程中,当满足设定条件时,程序中断

    注意:watch必须在程序运行的过程中设置观察点,即运行run之后,并且要保证条件表达式中的变量已经使用过。

    例1

    (gdb)break 13

    (gdb)run

    (gdb)watch sum==3

    例2

    (gdb)break 5

    (gdb)run

    (gdb)watch sum==3

    查看断点

    查看当前设置的断点

    格式: info breakpoints( info b

    例如:

    (gdb)break 7

    (gdb)break 15 if res==5050

    (gdb)info breakpoints

    管理断点

    1. 使中断失效或有效

    失效: disable [断点编号]

    有效: enable [断点编号]

    2. 删除断点

    clear [行号]: 删除此行的断点

    delete [断点编号]: 删除指定编号的断点, 若有一次删除多个断点,各断点编号以空格分开。

    delete: 删除程序中所有的断点

    3. 取消断点  d + 断点编号

    查看和设置变量的值

    当程序执行到中断点暂停时,往往需要查看变量或表达式的值,借此了解程序的执行状态,进而发现问题。

    1 print

    功能: 打印变量或表达式的值,还可以用来对某个变量进行赋值。

    print [变量或表达式]: 打印变量或表达式的值

    print [变量]=[值]: 对变量进行赋值 

    例如:

    (gdb)break 7

    (gdb)run

    (gdb)print i < n

    (gdb)print i

    (gdb)print sum

    (gdb)print i=200

    (gdb)continue

    2 whatis

    功能: 用于显示某个变量或表达式的数据类型

    格式: whatis [变量或表达式]

    例如:

    (gdb)break 7

    (gdb)run

    (gdb)whatis i

    (gdb)whatis sum

    (gdb)whatis sum+0.5

    3 set

    功能: 给变量赋值

    格式: set variable [变量]=[值]

    4.临时查看变量或地址的值:p + 变量或地址

    控制程序的执行

    当程序执行到指定的中断点时,完成相关的debug操作后,可以让程序继续运行

    1 continue

    程序继续运行,直到下一个断点或运行完毕(运行至下一个断点处:c(continue))

    2 kill

    结束当前程序的调试

    3 next/step

    功能: 一次一条执行程序代码(逐过程:n(next),逐过程:n(next)

    区别: next把函数调用当做一条语句来执行;step追踪进入函数,一次一条地执行内部代码。

    4.跳转到指定行:until+行号

    可以利用until来跳出循环

     

  • 相关阅读:
    C++QT开发——Xml、Json解析
    java项目-第128期ssm+oracle的宿舍管理平台-java毕业设计_计算机毕业设计
    RFID安全的三次认证
    设计模式之组合模式
    练习-Java输入输出之文件字节IO流之合并文件
    LeetCode 41. 缺失的第一个正数
    Spring系列文章:Spring6集成MyBatis3.5
    信奥中的数学基础:分解质因数 因式分解
    PHP redis key
    推荐系统实践读书笔记-07推荐系统实例
  • 原文地址:https://blog.csdn.net/qq_62377885/article/details/133840492