关于linux中gdb的问题?

0:gdb常用命令概述

一、GDB常用命令简介

运行.程序还没有运行前使用
执行下一行的代码。如果是函数调用,也当作一行代码,执行到此函数返回
删除断点:delete 断点号
列出代码行。一次列10 行。 也可在 list 后面跟上 文件名:行号
观察一个变量的值。每次中断时都会显示这个变量的值
打印一个变量的值。print 也可改变一个值,通过指令 p b = 100,变量b 的值就变成100了
从主函数 main 开始运行调试

和所有常用的调试工具一样,gdb提供了以下功能:
 # 监视程序中变量的值
 # 在程序中设置断点
 # 程序的单步执行

在使用gdb前,必须先载入可执行文件,因为要进行调试,文件中就必须包含调试信息,所以在用gcc或cc编译时就需要用-g参数来打开程序的调试选项。

调试开始时,必须先载入要进行调试的程序,可以用以下两种方式:
 * 在启动gdb后执行以下命令:
 * 在gdb启动时就载入程序:
   gdb 可执行文件路径

载入程序后,接下来就是要进行断点的设置,要监视的变量的添加等工作,下面对在这个过程中常会用到的命令逐一进行介绍:
 * list :显示程序中的代码,常用使用格式有:
      输出从上次调用list命令开始往后的10行程序代码。
      输出从上次调用list命令开始往前的10行程序代码。
      输出第n行附近的10行程序代码。
      输出函数function前后的10行程序代码。
  查找到的行号将保存在$_变量中,可以用print $_命令来查看。
 * break :在程序中设置断点,当程序运行到指定行上时,会暂停执行。使用格式:
    break 要设置断点的行号
 * tbreak :设置临时断点,在设置之后只起作用一次。使用格式:
    tbreak 要设置临时断点的行号
    clear 要清除的断点所在的行号
 * run :启动程序,在run后面带上参数可以传递给正在调试的程序。
  当表达式的值发生改变或表达式的值被读取时,程序就会停止运行。
 * watch :与awatch类似用来设置观察点,但程序只有当表达式的值发生改变时才会停止运行。使用格 式:
  需要注意的是,awatch和watch都必须在程序运行的过程中设置观察点,即可运行run之后才能设置。
 * commands :设置在遇到断点后执行特定的指令。使用格式有:
      设置遇到最后一个遇到的断点时要执行的命令
      设置遇到断点号n时要执行的命令
  注意,commands后面跟的是断点号,而不是断点所在的行号。
  在输入命令后,就可以输入遇到断点后要执行的命令,每行一条命令,在输入最后一条命令后输入end就可以结束输入。
 * delete :清除断点或自动显示的表达式。使用格式:
  断点号之间用空格间隔开。
      跳过当前断点继续运行。
      跳过n次断点,继续运行。
 * jump :让程序跳到指定行开始调试。使用格式:
 * next :继续执行语句,但是跳过子程序的调用。使用格式:
      执行一条语句
      执行n条语句
 * nexti :单步执行语句,但和next不同的是,它会跟踪到子程序的内部,但不打印出子程序内部的语句。使用格式同上。
 * step :与next类似,但是它会跟踪到子程序的内部,而且会显示子程序内部的执行情况。使用格式同上。
 * whatis :显示某个变量或表达式的数据类型。使用格式:
 * ptype :和whatis类似,用于显示数据类型,但是它还可以显示typedef定义的类型等。使用格式:
 * set :设置程序中变量的值。使用格式:
  表达式中有两个符号有特殊含义:$和$$。
  $表示给定序号的前一个序号,$$表示给定序号的前两个序号。
  如果$和$$后面不带数字,则给定序号为当前序号。

如要查看所有的gdb命令,可以在gdb下键入两次Tab(制表符),运行“help command”可以查看命令command的详细使用格式。

先要说点关于ios的事.

大家开发ios时用的最多的软件是mands

command命令里可以绑定很多函数.只要能够链接的到.库函数.你自己定义的函数都可以.甚至还可以使用函数的返回值.只要函数的返回值是int类型.

  
以上有几点要注意的地方 .
  1. watchpoint监视的是内存值的变化.如果内存值被赋予了一个一样的值.那也不会起作用.

  
watchpoint也可以像条件断点一样加上条件.它们的区别是watchpoint会在作用域之后自动删除.没前作用域之前不会存在.
条件监视断点里可以包含的表达式有:
  1. 类似$arg0这些已经在gdb中定义的变量.

  2. 任何在当前 scpoe里的变量

  3. 定义了的字符,数字常量

  
  

  
  
有没有发现上面的watchpoint type 是hw,这是因为watchpoint可以由硬件实现.速度很快.如果硬件不能实现gdb则会利用VM技术实现.也比较快.如果前两种都不行.GDB会自己通过软件实现..很慢.
前面已经把95%的调试技巧全讲完了.接下来一起学习一下方便调试的东西.这些命令或者技巧是能让你更方便的调试.
接下来将介绍以下高级命令
display //在每次断点停下来时,打印当前scope中的变量
怎么查看当前stack中的变量?
怎么打印其他格式的值?
怎么临时改变变量的值?
怎么设置启动时的命令行参数?
为什么每次print时,都有1,2之类的东东在前面?
怎么在gdb中设置一个变量?


  

  

怎么查看当前stack中的变量?

 
  
  

怎么打印其他格式的值?

  
  

  
这个跟断点Num的意义一样.是display某值的一个标识.
  

怎么临时改变变量的值?

  
  

怎么设置启动时的命令行参数?

  
  
当然.你设置完后.要调用run启动这些命令.跟直接执行以下是一样的
  

为什么每次print时,都有1,2之类的东东在前面?

  
这个东西叫 value history. 恶心翻译一下就是值的历史吧. 比如说你打印
  

  

怎么在gdb中设置一个变量?

  
  

  
大家觉得下面两个函数有什么区别? 麻烦用call命令在gdb中分别调用它们(跟gdb没关系.只是顺便举例).
发现区别没有.printf不一定要会即时调用.我建议大家看一下这篇文章. .
这一篇主要说一下类的一些相关调试.

  

怎么打印类中的静态变量?

  
  

  
  
调试中最烦的就是线程. 线程太多队伍不好带...
在mac下.线程用的最多的还是pthread. 先准备好要调试的线程源码:
在断点停下后.怎么切换到其他线程去
怎么指定在某个断点停下,当在某个线程时.
9为什么你的程序会崩溃?
  
在写c/c++程序时.最常见的崩溃就是
invalid access of memory 读取了没有权限的内存导致崩溃.出现这种情况时. 硬件会执行一个jump命令到操作系统.由操作系统处理.
正是因为在调试时内存是在虚拟内存里分配的.所以有一些segmentation fault不是很明显.原因是:
在VM里的内存分配有一个最小分配值.取名叫page. 在奔腾系统处理器里.这个值默认为4096 bytes.所以当你有一个程序占用了10000 bytes时.它总共会占用3个page.而不是2.5个.page已经是最小单位.不能再分割.
这就会出现一个问题.如果程序在多出来的page里出了错.很可能在调试时并不会报错.

Gdbserver是一个运行在Linux上的调试工具,用于调试Linux上运行的应用程序。当目标系统是一个嵌入式系统时,可能因为资源的限制而不能运行全功能版本的gdb,这个时候gdbserver就显得格外的有用了。

Visual Studio Preview 1添加了一项新的特性:使用gdbserver对CMake工程进行远程调试。在之前的一篇文章中,我们描述了如何在Linux docker容器中编译CMake应用程序。在今天的文章中,我们将在前篇文章的基础上涵盖如下的内容:
2. 拷贝编译生成的文件到本机。
3. 部署生成的程序到另外一个独立的ARM linux系统(通过SSH进行连接),并借助ARM系统上的gdbserver和本机上的gdb来进行远程调试。

通过在本机上使用一个特定版本的gdb,可以避免在远程(嵌入式)系统上施一公全功能版本的gdb。
请注意,以上流程目前只是VS Preview 1中的一项实验特性,并需要一些手动的配置才能工作。

这篇文章假设你已经成功配置了VS2019并可以在一个Linux docker容器(Ubuntu)中编译一个CMake工程。如果你对这块还有点不明白,可以参考我之前的一篇文章。
为这个流程所进行的配置是比较通用的,也就是说,你可以在任何Linux环境(一台VM,或者一台远程Linux服务器等)来做相同的配置步骤。

第一件事,是需要修改我们的配置文件来进行ARM的交叉编译。在之前的文章中,我们创建了一个Dockerfile,我们基于这个Dockerfile做了如下的改动:

在以上的Dockerfile中,我使用apt-get来安装了一个交叉编译器并从本机拷贝了一个CMake配置文件到Docker容器中。CMakeCMake是一个需要安装的依赖项,但是从上一篇文章中我们可以通过部署一个静态链接的版本来解决这个依赖问题。

CMake工具链文件指定了有关编译器和相关工具的路径信息。我在这里使用了一个CMake的例子文件来在Windows上创建一个配置文件,其内容如下:

保存这个文件为”arm_toolchain.cmake”到Dockerfile所在的文件夹。另外,我们也可以通过在上面COPY命令中添加到此文件的相对路径。

至此,我们可以编译一个Docker映像并执行了。

最后,我们可以通过SSH来直接和Docker容器进行交互,并创建一个用户账号。请注意再次提醒,你可以在Dockerfile中启用root登录,这样可以避免所有的手动操作。只需要替换为你想要使用的用户账号即可,如下图所示:

这样,你就可以准备好从Visual Studio中进行编译了。

请注意,每次你修改以上配置,都需要记得删除配置文件的缓存版本(Project > CMake Cache (arm-Debug only) > Delete Cache)。如果你没有安装CMake,VS会提示你在远程机器上安装一个静态链接的版本,作为配置过程的一部分。

你的CMake工程已经完成配置,准备可以在Linux Docker容器中进行ARM交叉编译了。当你编译程序的时候,你将会在远程机器(/home//.vs/…)和本机上看到编译输出的文件。

接下来,我们将在连接管理器中创建一个新的远程连接。这个是我们将要部署的目标系统,其运行的是OS Raspbian (ARM)系统。请确保ssh正常运行在这个系统上。

WSL。而且它还不支持多个localhost连接。这个限制主要是因为一个bug,我们会在VS的下一个版本中得到修复。在这种情况下,你的Docker连接将会是唯一一个localhost连接,并且可以通过SSH来连接ARM系统。

我们将会手动的配置这个文件(包括添加或删除一些属性)来启用gdbserver调试。
以下是配置文件的一个例子,供参考。请注意,这项支持还比较新,仍然需要一些手动的配置步骤。

现在可以在程序中设置一个断点,并确保arm-Debug是当前激活的配置项,并且当前的调试器为gdbserver,如下图所示:

当按下F5时,工程将会在CMakeSettings.json中配置的远程系统上开始编译,并部署到launch.vs.json中指定的系统中。同时,本机调试会话也将会启动。

1. 如果launch配置没有正确配置,那么你将可能不能连接远程机器。所以,请确保清除掉你将要部署的系统上的所有gdbserver进程。
2. 如果你没有修改CMake配置中的remote build root,则在远程系统上的程序的相对路径将和远程编译环境中的相对路径一致。

所以说:编译,部署,调试,一切的一切,Visual Studio都给安排的明明白白了?

我使用GDB附加到正在运行的进程并捕获断点。 我执行以下命令序列:

现在,我打开了GUI TUI视图,而没有任何源文件。

我一直在拼命尝试用Google加载/打开源文件以执行命令" break"的方法,但是不幸的是,我找不到任何可以正常工作的东西。


我也有同样的问题; 如此令人惊讶的是,如此基本的功能如此晦涩。 我的解决方法是使用文件名和函数名来设置断点:


阅读GDB文档的检查源文件一章。

您可以使用list命令。

当然,您需要适当地设置目录列表。 使用dir命令。

GDB文档以教程章节开头,因此请阅读。

当然,所有软件都应使用-g(甚至是-g3)进行编译,以从编译器中获取其调试信息。

顺便说一句,您的源文件已经被gdb打开(即可见)。 您可能要list部分,或在其中放置一个断点(使用break或tbreak)。 不需要您采取任何特定的措施即可使其对gdb可见(也许dir命令除外)。


我要回帖

更多关于 linux vim编辑器 的文章