调试工具gdb

1.1 gdb符号调试器简介

  gdb是一个用来调试C和C++程序的功能强大的调试器,它能在程序运行时观察程序的内部结构和内存的使用情况。

  gdb主要提供以下几种功能:

  • 监视程序中变量值的变化
  • 设置断点,使程序在指定的代码行上暂停执行,便于观察
  • 单步执行代码
  • 分析崩溃程序产生的core文件

    gdb filename(执行文件名)

    编译时需加上-g 或 -ggdb3 选项

1.2 gdb功能详解及其应用

  1.2.1调试步骤

    1.调用gdb

      gdb filename

    2.设置断点并调试

      break functionname/linenumer

      run 执行程序

      step 单步跟踪程序代码

    print命令:

      print 表达式

      print 变量=表达式

      print 开始表达式@要打印连续内存空间的大小

    display命令:

      display 表达式

      在使用display命令时,每次调试器中断程序,挂起指令都要显示变量的值

    next命令:

      不进入函数内部

    quit命令:

      退出gdb

  1.2.2 显示数据命令

    1. print命令与display命令

    finish 执行完当前函数

    2. 内存检查命令

      x /format address

        format指显示单元的个数以及显示的格式

      例如:x/2c 0x120100fa0

    3.printf      类似于c里的printf()函数

      例如:printf"%2.2s\n",(char*)0x120100fa0

    4.使用set命令

      set variable 变量=表达式                      设置变量值

  1.2.3 使用断点

    continue命令和cont命令(cont 数字  表示执行数字次继续)

    break 行号

    break 函数名

    条件断点:

      condition 断点编号 表达式                   程序在表达式为真时中断

    tbreak  行号  临时断点

    (break  行号

       enable delete 断点号)等效于临时上一个断点

    enable  断点编号                恢复失效断点

    disable  断点编号     使断点失效

    delete    断点编号或表达式        清除断点(无提示信息)

    clear   要清除的断点所在行号      清除断点(有提示信息)

  1.2.4 使用观察窗口

    watch  表达式                     如果表达式中某个变量的取值超过了范围,就不能再对表达式取值了。这一点与条件断点设置不同,因为它只在代码的固定位置取值。

  1.2.5 查看栈信息

    backtrace

    bt

    bt n  栈顶上n层栈信息

    bt -n  栈顶下n层栈信息

    frame n

    f n          n是一个从0开始的整数,是栈中的层编号。比如:frame 0表示栈顶,frame 1表示栈的第二层

    up n  表示向栈的上面移动n层,不输入n表示移动一层

    down n  表示向栈的下面移动n层

    以下为不带提示信息的移动栈层信息:

      select-frame n

      up-silently n

      down-silently n

      ---------------

      frame 或 f               查看当前栈层信息(包括栈层编号,当前函数名,函数参数值,函数所在文件及行号,函数执行到的语句)

      info frame 或 info f    该命令会显示更为详细的当前栈层的信息,只不过大多数都是运行时的内地址。

      info args  显示出当前函数的参数名及值

      info locals  显示出当前函数中所有局部变量的值

      info catch  显示当前函数中的异常处理信息      

     1.2.6 查看源程序

    1. 显示源代码 

      list <linenum>    显示程序第linenum行的周围的源程序。

      list <function>    显示函数名为function的函数的源程序

      list          显示当前行后面的源程序

      list -          显示当前行前面的源程序

      set listsize <count>  设置一次显示源代码的行数

      show listsize  查看当前listsize的设置

      list <first>,<last>  显示从first行到last行之间的源代码

      list ,<last>  显示当前行到last行之间的源代码

      list +  向后显示源代码

      一般来说,在list后面可以跟以下这些参数。

      <linenum>:行号。

      <+offset>:当前行号的正偏移量

      <-offset>:当前行号的负偏移量

      <filename:linenumber>:哪个文件的哪一行

      <function>:函数名

      <filename:function>:哪个文件的哪个函数

      <*address>:程序运行时的语句在内存中的地址

    2.搜索源代码

      forward-search <regexp>

      search <regexp>  向前搜索

      reverse-search <regexp>  全部搜索

    3.指定源文件的路径

      directory <dirname ...>

      dir <dirname ...>

      directory  清除所有自定义源文件搜索路径信息

      show directories  显示定义了源文件搜索路径

    4.源代码的内存

      info line  行号/函数名

      info line 文件名:行号/文件名:函数名

      disassemble func  查看func的汇编代码

      disassemble address

  1.2.7 查看运行时数据

    1.表达式

      @  一个和数组有关的操作符

      ::  指定一个在文件或是一个函数中的变量

      {<type>} <addr>   表示一个指向内存地址<addr>的类型为type的一个对象

    2.程序变量

      全局变量(所有文件可见)

      静态全局变量(当前文件可见的)

      局部变量(当前Scope可见的)

      示例:

        file::variable

        function::variable

        p 'f2.c'::x

    3.数组

      例如:程序中有如下语句

        int *array = (int *)malloc(len * sizeof(int));

      p *array@len

      如果是静态数组的话,直接用"print 数组名"就可以显示数组中所有数据的内容了。

    4.输出格式

      x  按十六进制格式显示变量

      d  按是禁止格式显示变量

      u  按十六进制格式显示无符号整形

      o  按八进制格式显示变量

      t  按二进制格式显示变量

      a  按十六进制格式显示变量

      c  按字符格式显示变量

      f  按符点数格式显示变量

    5.查看内存

      x/<n/f/u> <addr>  nfu是可选参数。

                n表示显示内存的长度,

                f表示显示的格式,

                u表示从当前地址往后请求的字节数,如果不指定的话,gdb默认是4个bytes。

                u可用以下字符来代替:b表示单字节,h双字节,w四字节,g八字节。

                addr表示一个内存地址。

      示例:

      x/3uh 0x54320    以无符号整形双字节为单位显示从地址0x54320开始的3个长度的内存中的内容

    6.自动显示

      可以设置一些自动显示的变量,当程序停住时,或是在单步跟踪时,这些变量会自动的显示。

      display <expr>

      display/<fmt> <expr>

      display/<fmt> <addr>

      格式i和s同样被display支持,一个非常又用的命令是:

      display /i $pc    $pc是gdb的环境变量,表示指令的地址,/i则表示输出格式为机器指令码,也就是汇编。与是当程序停下后,就会出现源代码和机器码相对应的情形。

      undisplay <dnums...>

      delete display <dnums...>

        删除自动显示,dnums意为设置好了的自动显示的编号。如果要同时删除几个编号,可以用空格分隔;如果要删除一个范围内的编号,可以用减号表示。

      disable display <dnums...>

      enable display <dnums...>

        不删除自动显示的设置,而只是让其失效和恢复,而只是让其失效和恢复。

      info diaplay

        查看display设置的自动显示的信息。gdb会显示出一张表格,报告中设置了多少个自动显示设置,其中包括设置的编号,表达式以及是否enable。

    7.设置显示选项

      set print address on/off  显示函数参数地址  系统默认打开

      show print address    查看当前地址显示选项是否打开

      set print array on/off      打开/关闭数组显示,打开后数组显示时每个元素占一行;关闭时每个元素以逗号分隔。这个选项默认时关闭的。

      show print array

      set print elements <number-of-elements>  这个选项主要时设置数组的,如果数组太大了,就可以指定一个<number-of-elements>来指定数据显示的最大长度,当达到这个长度时,gdb就不再往下显示了。如果设置为0,则表示不限制。

      show print elements

      set print null-stop <on/off>  如果打开了这个选项,那么当显示字符串时,遇到结束符则停止显示。这个选项默认为off。

      set print pretty on/off  选项打开时,当gdb显示结构体时会比较漂亮。

      show print pretty

      set print sevenbit-stirngs <on/off>   设置字符显示,是否按“\nnn”的格式显示。如果打开,则字符串或字符数据按\nnn显示,如“\065”

      show print sevenbit-stirngs

      set print union <on/off>    设置显示结构体时,是否显示其内的联合体数据。

      show print union  查看联合体数据的显示方式

      set print object <on/off>  对象选项设置。在C++中,当一个对象指针指向其派生类时,如果打开这个选项,gdb会自动按照虚方法调用的规则显示输出,如果关闭这个选项,gdb就不管虚函数表了。这个选项默认为off。

      show print object  查看对象选项的设置

      set print static-members <on/off>  这个选项表示,当显示一个C++对象中的内容时,是否显示其中的静态数据成员。默认为on。

      show print static-members  查看静态数据成员选项设置

      set print vtbl <on/off>  当此选项打开时,gdb将用比较规整的格式来显示虚函数表。其默认是关闭的。

      show print vtbl  查看虚函数显示格式的选项

    8.历史记录

      每一个print命令都会被gdb记录下来。gdb会以$1,$2,$3......这样的方式为每一个print命令编上号。于是,可以使用这个编号访问以前的表达式,如$1。

    9.gdb环境变量

      可以在gdb调试环境中定义自己的变量,用来保存一些调试程序中的运行数据。

      环境变量没有类型,可以给环境变量定义任意的类型,包括结构体和数组。

      set $foo = *object_ptr

      show convenience  查看当前所设置的所有的环境变量

      (set i = 0

      print bar[$i++]->contents)  这个一个比较强大的功能,环境变量与程序变量的交互使用使得程序调试更为灵活便捷。输入这样的命令后,按下Enter键,重复执行上一条语句,环境变量会自动增加,从而完成逐个输出的功能。  

    10.查看寄存器

      info registers  查看寄存器的情况(除了符点器存器)

      info all-registers  查看所有寄存器的情况

      info registers <regname...>   查看指定寄存器的情况

  1.2.8 改变程序的执行

    1.修改变量值

      print x=4

      whatis width  

      set var width=47

    2.跳转执行

      jump <linespec>  <linespec>可以是文件的行号,可以是file:line格式,可以是+num这种偏移量格式。表示下一条语句从哪里开始。

      jump <address>  这里的<address>是代码行的内存地址。

      建议在同一个函数内调转

      熟悉汇编的人都知道,程序运行时有一个寄存器用于保存当前代码所在的内存地址。所以,jump命令也就是改变了这个寄存器中的值。可以使用set $pc来更改调转执行的地址。如:

      set $pc=0x485

    3.产生信号量

      使用signal命令可以产生一个信号量给被调试的程序。如中断信号Ctrl+C。这非常方便与程序的调试,可以在程序运行的任意位置设置断点,并在该断点用gdb产生一个信号量。精确地在某处产生信号非常有利程序的调试。其语法是:

      signal <signal>

        Linux的系统信号量通常从1-15,所以<signal>也在这个范围。

    4.强制函数返回

      如果调试断点在某个函数中,还有语句没有执行完,可以使用return命令强制函数忽略还没有执行的语句并返回。

      return

      return expression

      使用return命令取消当前函数的执行,并立即返回。如果指定了<expression>,那么该表达式的值会被当作函数的返回值。

    5.强制调用函数

      call <expr>    表达式中也可以是函数

      另一个相似的命令也可以完成这一功能--print。print后面可以跟表达式,所以也可以用它来调用函数。print和call不同之处是,如果函数返回void,call则不显示,print则显示函数的返回值,并把该值存入历史数据中。

    6.在不同语言中使用gdb

      show language  查看当前语言环境

      info frame  查看当前函数的程序语言

      info source  查看当前文件的程序语言

      set language   如果set language后面什么也不跟,可以查看gdb所支持的语言种类。可以在set language 后面加上被列出的语言名,来设置当前的语言环境。

  1.2.9 core dump分析

    在进行程序开发时,常常由于种种原因导致程序崩溃。这时可以使用Linux下的core dump功能。在程序崩溃时,Linux会创建一个core文件,在程序结束后,利用这个文件中的信息,在使用gdb,就能指导程序崩溃时在做些什么。但core dump功能并不是所有的程序员都可以使用的,这是因为一些发行版和一些系统的管理员在默认时禁止使用core dump。可以使用ulimit -c unlimited

    这样就能使用core文件分析了。

    编译生成可执行文件test,然后运行./test生成core文件

    gdb test core

    bt(即backtrace)命令用来打印stack frame(栈桢)指针,可以了解当前程序运行过程中的函数之间的调用关系。

    使用frame命令:

      frame命令是用来打印栈桢的,它使用如下格式。

      frame 要打印的栈桢的编号  如果没有指定栈桢时,gdb会打印当前选择的栈桢

      可以使用info frame命令查看当前所选择的栈桢,它将给出栈桢的详细信息。

1.3 其他调试工具

  xxgdb  是X-Windows系统的调试工具,实际上它图形化的gdb,保留了gdb所有的特性。

1.4 小结

  在软件开发中出现错误在所难免,所以程序的调试就成为软件开发中非常重要的一个环节,gdb就是Linux系统下C程序调试工具中最常用的一种。本章首先介绍了gdb的程序调试步骤,进而深入地阐述了它的功能和一些高级调用方法。最后简单介绍了另一种调试工具。

转载于:https://www.cnblogs.com/wtsgtc/p/9317607.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/366468.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Apache Camel –从头开始开发应用程序(第1部分/第2部分)

开始之前 前一段时间&#xff0c;我写了一篇关于Spring Integration的教程&#xff0c;以演示如何在受现实发票处理系统启发的示例应用程序中使用Spring Integration。 我对此非常满意&#xff0c;因此我决定向您展示如何使用Apache Camel&#xff08;Spring Integration的最大…

Bourbon: 让你的sass更简洁

Bourbon是什么 bourbon是一个轻量级的Sass mixin和函数库&#xff0c;可以帮助我们快速开发样式. 官方文档 以下用webpack3.10.0( vue)为示例简述Bourbon的使用 安装配置 npm install bourbon -S 把bourbon添加到node-sass的includePaths中// webpack.config.js module.expor…

nat的地址映射 华为_华为PAT端口地址映射配置详解(一)

众所周知&#xff0c;PAT,&#xff0c;Port Address Translation&#xff0c;即网络地址转换。PAT有以下作用&#xff1a;1.改变数据包的ip地址和端口号&#xff1b;2.能够大量节约公网IP地址。PAT的类型有以下&#xff1a;1.动态PAT&#xff0c;包括NAPT和Easy IP&#xff1b;…

删除maven仓库中的lastUpdate文件

windows下打开命令行 进入maven本地仓库目录中 dos命令中执行下方命令.即可完成批量删除 for /r %i in (*.lastUpdated) do del %i 转载于:https://www.cnblogs.com/zlsxddgj/p/9324077.html

HDUOJ 1428

漫步校园 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5161 Accepted Submission(s): 1610 Problem DescriptionLL最近沉迷于AC不能自拔&#xff0c;每天寝室、机房两点一线。由于长时间坐在电脑边&#xff…

niosii spi 外部_基于Nios_II的DMA传输总结

最近练了一段时间的DMA传输&#xff0c;现做如下的总结&#xff0c;分享自己获得心得以及遇到的一些问题。在系统运行时&#xff0c;当需要传输大量数据时&#xff0c;可以采用DMA的方式进行传输&#xff0c;以解脱出CPU来处理其他命令。Nios II中的DMA传输有以下三种形式&…

杭州 GraphQLParty 第五场-GraphQL 基于 SPA 架构的工程实践文字版

本文为 2018 年 6 月 9 日&#xff0c;宋小菜与 Coding 共同举办的第一届 GraphQLParty &#xff0c;下午第五场国内某大型电商前端开发专家邓若奇的演讲稿&#xff0c;现场反响效果极好&#xff0c;对于想要尝试 GraphQL 和在公司初步实践的团队有很大的借鉴意义。 大家好&…

java反射机制基础总结

1反射机制是啥&#xff1f; 反射是运行中的程序检查自己和软件运行环境的能力&#xff0c;它可以根据它发现的进行改变。通俗的讲就是反射可以在运行时根据指定的类名获得类的信息。 2反射机制有啥用&#xff1f; Reflection(反射)是被视为动态语言的关键反射机制使程序在执行期…

使用sikuli和Arquillian测试HTML5 canvas应用程序

HTML5引入了一个很棒的新元素&#xff0c;可以用来在窗格上绘制任意内容&#xff1a; canvas元素。 数十年来&#xff0c;胖客户端应用程序的标准功能现已引入Web应用程序领域。 Web开发人员不再需要使用专有插件在其应用程序中绘制图像或图表。 但是&#xff0c;在进行测试时…

浅谈一下我了解的PWA

Progressive Web Apps,简称PWA&#xff0c;中文翻译过来就是渐进式网页应用&#xff0c;个人觉得它可以算是Web应用的下一个进化方向之一&#xff0c; 毕竟技术的发展有时候是不可预估的&#xff0c;谁也无法预料技术的走向&#xff0c;但至少它代表了一种可能性&#xff0c;下…

质性研究工具_质性研究【001】

袁长蓉 复旦大学 博士研究生导师课程 人类是追求意义的物种&#xff0c;会不断地从生活细节当中不断的归纳提炼&#xff0c;形成精神。形成理论抽象的概念&#xff0c;然后再利用这些概念&#xff0c;这些理论反过来&#xff0c;解释生活。 质性研究是由地到天的研究。质性研究…

python实现文件下载图片视频

最近在学习爬虫&#xff0c;在爬取网站时很多时候是需要将图片或视频下载到本地 今天就来说说如何使用urllib将图片保存到本地 以下代码均为win7 python3.6.* 方法一&#xff08;使用下载函数保存&#xff09; from urllib import request # 要下载的图片链接地址 img_url …

在JUnit中处理异常的3种方法。 选择哪一个?

在JUnit中&#xff0c;有3种流行的方式来处理测试代码中的异常&#xff1a; 尝试捕捉习语 使用JUnit规则 带注解 我们应该使用哪一个&#xff1f;何时使用&#xff1f; 尝试捕捉习语 这个习语是最受欢迎的习语之一&#xff0c;因为它已在JUnit 3中使用。 Testpublic void…

项目开发中发布更新文档备注

项目开发中 经常会遇到 某一个团队成员更新了,配置文件但是没有及时沟通导致项目发布后出现异常的情况。 这时就需要一个项目更新发布的规范说明文件,比如每次更新更改了哪些,进行文档备注。 更新的脚本文件也要随更新文档一起给到,配置文件也要将最新的配置信息给到。 转载于:…

bind函数polyfill源码解析

准备知识 使用new来调用函数会自动执行下面的操作&#xff1a; 创建一个全新的对象这个新对象会被执行原型连接这个新对象会绑定到函数调用的this如果函数没有返回其他对象&#xff0c;那么new表达式中的函数调用会自动返回这个新对象 注意this绑定规则&#xff0c;new操作具…

Java方法中的参数太多,第2部分:参数对象

在上一篇文章中 &#xff0c;我研究了与方法和构造函数的长参数列表相关的一些问题。 在那篇文章中&#xff0c;我讨论了用自定义类型替换基元和内置类型以提高可读性和类型安全性。 这种方法使方法或构造函数的众多参数更具可读性&#xff0c;但并没有减少参数的数量。 在本文…

django内置服务器

单进程多线程的 多线程用来并发&#xff0c;各个线程之间不会阻塞&#xff0c;每个线程对应一个连接转载于:https://www.cnblogs.com/BlueFire-py/p/10031245.html

java mysql_Java与mysql的连接

接触编程、计算机一段时间&#xff0c;免不了的就要接触到&#xff0c;各种数据&#xff0c;而各种数据到了深处自然就要接触到数据的存储和调用&#xff0c;之前在我的文章中&#xff0c;已经了解到了IO流在文件中以及在TCP\IP协议中的各种传输&#xff0c;而慢慢的&#xff0…

Oracle 创建wims用户和表空间

/*用sys SYSDBA *//*分为四步 *//*第1步&#xff1a;创建临时表空间 */create temporary tablespace xxxxxxx_temp tempfile D:\app\Administrator\oradata\orcl\xxxxxxx_temp.dbf size 50m autoextend on next 50m maxsize 20480m extent management local; /*第2步&#xff1…

面试常见问题之实现bind函数

前言&#xff1a; 原文首发于我的博客&#xff0c;说实话&#xff0c;这半年来在各大社区看别人分享的面试题中 bind 函数已经出现 n 多次了&#xff0c;这次准备详细探究下 首先让我们看看 mdn 对于 bind 函数的描述是什么 语法 fun.bind(thisArg[, arg1[, arg2[, ...]]]) 参…