

文章目录
但是如何对一段代码去进行调试呢,此时就要使用到Linux下的调试器gdb了。对于这个调试器来说,不像是VS中那样的图形化界面形式,而是采用纯命令行的形式进行调试。可能我的讲解会比较晦涩难懂,在学习的过程中主要是会一些gdb下基本的操作即可
下面是本次调试所要使用到的代码
1 #include <stdio.h>
2
3 int AddToTop(int top)
4 {
5 printf("Enter AddToTop\n");
6
7 int count = 0;
8 for(int i = 1;i <= top; ++i)
9 {
10 count += i;
11 }
12
13 printf("Quit AddToTop\n");
14 return count;
15 }
16
17 int main(void)
18 {
19 int top = 100;
20 int ret = AddToTop(top);
21
22 printf("ret = %d\n", ret);
23 return 0;
24 }
下面是Makefile中的内容,用于自动化编译
1 mytest:test.c
2 gcc -o mytest test.c -std=c99
3 .PHONY:clean
4 clean:
5 rm -rf mytest
注:-std=c99表示以c99的标准来编译代码
gdb + 可执行程序即可
q(quit)退出gdb让我们先看下去,了解一下其他的知识再来解决这个问题
接下去我们就来说说有关【DeBug】和【Release】版本的不同之处
📚【Debug】—— 调试版本
📚【Release】—— 发布版本
测试人员进行测试,而且会给出自己的单元测试报告。对于测试人员来说所处的模式是【Release】,也就是将来客户要使用的这款软件的发布版本其实对于我们刚才直接make自动化生成的可执行程序是通过gcc直接编译产生得到的,它是一个【Release】版本的可执行程序,因此无法进行调试
gcc/g++去生成一个可执行程序时,默认是【Release】版本的,而不是【DeBug】-g的命令选项,此时再去make一下的话生成的就是【DeBug】版本的了mytest-releasemytest-debug
通过观察上图中两个可执行文件的大小便可以发现虽然它们都是可执行程序,但是容量大小却不一样,这是为什么呢❓
因为以Release版本发布的软件是给客户的,客户是不需要调试信息的
往可执行程序里添加很多的调试信息意味着软件的体积会变大
但是对于DeBug来说会自动加调试信息,容量体积比Release大
但是就这么说说太抽象了,我们得看看这个可执行文件里的调试信息究竟是怎样的💻
readelf -S mytest-debug

当我们面对一堆二进制乱码措手不及的时候,给大家提到过一个东西叫做readelf,其实它是Linux中的一个指令,可以用来读取【elf】格式的文件
-S的命令选项以符号表的形式来进行读取这个文件,就以一个列表的形式展现出了这个带调试信息的可执行程序.rodata就是read only data即只读全局数据区.data就是已初始化全局数据区.bss就是未初始化全局数据区
grep命令来进行一个筛选。便可以查看到所有的debug调试信息了

【总结一下】
-g选项好,说到这里,对于调试相关背景就全部讲完了,接下去我们正式进入【gdb】的学习⌨️
因为这个调试器是在Linux环境下的,是纯命令行模式,所以会有很多的指令,做好心里准备😢
注:()括号里面是该指令的全称
l(list) 行号/函数名—— 显示对应的code,每次10行
r(run)—— F5【无断点直接运行、有断点从第一个断点处开始运行】
b(breakpoint) + 行号—— 在那一行打断点
b 源文件:函数名—— 在该函数的第一行打上断点
b 源文件:行号—— 在该源文件中的这行加上一个断点吧
info b—— 查看断点的信息breakpoint already hit 1 time【此断点被命中一次】
d(delete) + 当前要删除断点的编号—— 删除一个断点【不可以d + 行号】
- 若当前没有跳出过gdb,则断点的编号会持续累加
d + breakpoints—— 删除所有的断点
disable b(breakpoints)—— 使所有断点无效【默认缺省】
enable b(breakpoints)—— 使所有断点有效【默认缺省】
disable b(breakpoint) + 编号—— 使一个断点无效【禁用断点】
enable b(breakpoint) + 编号—— 使一个断点有效【开启断点】
- 相当于VS中的空断点
enable breakpount—— 使一个断点有效【开启断电】
n(next)—— 逐过程【相当于F10,为了查找是哪个函数出错了】
s(step)—— 逐语句【相当于F11,】
bt—— 看到底层函数调用的过程【函数压栈】
set var—— 修改变量的值
p(print) 变量名—— 打印变量值
display—— 跟踪查看一个变量,每次停下来都显示它的值【变量/结构体…】
undisplay + 变量名编号—— 取消对先前设置的那些变量的跟踪排查问题三剑客🗡
until + 行号—— 进行指定位置跳转,执行完区间代码finish—— 在一个函数内部,执行到当前函数返回,然后停下来等待命令c(continue)—— 从一个断点处,直接运行至下一个断点处【VS下不断按F5】
看了上面的这些命令后,相信你一定回到了刚开始学习Linux指令的时候那种恐惧感,不过没关系,我会一一地演示这些指令,让你在看完本文后有一个基本的调试能力💪

l(list) 行号/函数名 —— 显示对应的code,每次10行


Enter几次就可以了,gdb会自动记忆你上次敲入的指令
b + 行号 —— 在那一行打断点

b 源文件:函数名 —— 在该函数的第一行打上断点

b 源文件:行号 —— 在该源文件中的这行加上一个断点

info b —— 查看断点的信息

b/breakpoint
来简要介绍一下断点的一些字段信息

breakpoint already hit 1 time即此断点被命中1次d + 当前要删除断点的编号 —— 删除一个断点【不可以d + 行号】

d + breakpoints —— 删除所有的断点


disable b(breakpoints) —— 使所有断点无效【默认缺省】

enable b(breakpoints) —— 使所有断点有效【默认缺省】

disable b(breakpoint) + 编号 —— 使一个断点无效【禁用断点】

enable b(breakpoint) + 编号 —— 使一个断点有效【开启断点】

其实对于禁用断点和启用断点,VS中也是有的,它叫做【空断点】。我们一起来看看


r(run) —— F5【无断点直接运行、有断点从第一个断点处开始运行】


n(next) —— 逐过程【相当于F10,为了查找是哪个函数出错了】

s(step) —— 逐语句【相当于F11,一次走一条代码,可进入函数,同样的库函数也会进入】
AddToTop这个函数,若是你在printf()语句要执行时按下【s】的话gdb就会进入printf()库函数内部去执行,这里就不展示了
Enter就可以了
p(print) 变量名 —— 打印变量值

i的值和count的值发生了变化
但是你不觉得这样每次去打印会显得很繁琐吗,那一定会的,所以我们有更好的办法💡
display —— 跟踪查看一个变量,每次停下来都显示它的值【变量/结构体…】


undisplay + 变量名编号 —— 取消对先前设置的那些变量的跟踪
display,那就有undisplay
bt —— 看到底层函数调用的过程【函数压栈】

AddToTop函数和main函数也呈现这样的关系。此时我们就可以通过【bt】这个指令来查看函数压栈的过程,此时便可以看到因为
set var —— 修改变量的值

我们也可以到VS中来看一下条件断点是如何设置的
在右击选择【条件】后,就可以输入你本次执行代码想要从哪个条件开始,然后按下Enter,启动调试之后就会从你设置的条件处开始执行

掌握了上面的这些,你就可以在Linux下调一些简单的代码了,不过想做到高效地进行调试,就需要学习一下【三剑客】
until + 行号 —— 进行指定位置跳转,执行完区间代码
until 13之后,程序直接就给出了我们最终的结果count,而且即将要执行最后的打印语句,说明我们跳转成功了

finish —— 在一个函数内部,执行到当前函数返回,然后停下来等待命令
finish,可以看到它直接回到了调用函数的位置,returned了一个返回值

c(continue) —— 从一个断点处,直接运行至下一个断点处【VS下不断按F5】

📖纸上得来终觉浅,绝知此事要躬行🔨
————————————
以下是本次调试所要使用到的代码,相信你一定非常熟悉了,也就是使用指针交换两数,如果想看细节讲解可以看看我的函数章节
1 #include <stdio.h>
2
3 void swap(int* x, int* y)
4 {
5 int t = *x;
6 *x = *y;
7 *y = t;
8 }
9 int main(void)
10 {
11 int a = 10;
12 int b = 20;
13
14 printf("a = %d, b = %d\n", a, b);
15
16 swap(&a, &b);
17
18 printf("a = %d, b = %d\n", a, b);
19 return 0;
20 }






t = *x时,临时变量t中已经存放了变量a的值,也就是指针所指向的那块空间中的值
*x = *y,此时*x中的值就发生了变化,因为指针x可以直接找到变量a的地址,所以可以对其中的内容做修改,就变为了20
*y = t,同理,指针y可以直接找到变量b的地址,所以可以对其中的内容做修改,将原本保存在临时变量t中的10赋值给到*y,也就修改了其中的内容

敲黑板:重点来了
通过以上的实验演练,你是否对调试器GDB的使用更上一层楼🐧
最后来总结一下本文所学习的内容📖
no debugging symbols】的报错信息,于是便谈到了一个可执行程序的【DeBug】版本和【Release】版本,知道了对于前者来说是我们程序员使用的环境,是存在调试信息的;对于后者来说是测试人员所处的环境,是不存在调试信息的。而对于gcc/g++而言默认生成的可执行程序就是【Release】版本的,因此我们要加上一个-g命令选项使其在make之后生成一个【DeBug】版本的可执行程序,这样就可以进行调试了以上就是本文要介绍的所有内容,感谢您的阅读❤️

我想用ruby编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序
GivenIamadumbprogrammerandIamusingrspecandIamusingsporkandIwanttodebug...mmm...let'ssaaay,aspecforPhone.那么,我应该把“require'ruby-debug'”行放在哪里,以便在phone_spec.rb的特定点停止处理?(我所要求的只是一个大而粗的箭头,即使是一个有挑战性的程序员也能看到:-3)我已经尝试了很多位置,除非我没有正确测试它们,否则会发生一些奇怪的事情:在spec_helper.rb中的以下位置:require'rubygems'require'spork'
使用Ruby1.9.2运行IDE提示说需要gemruby-debug-base19x并提供安装它。但是,在尝试安装它时会显示消息Failedtoinstallgems.Followinggemswerenotinstalled:C:/ProgramFiles(x86)/JetBrains/RubyMine3.2.4/rb/gems/ruby-debug-base19x-0.11.30.pre2.gem:Errorinstallingruby-debug-base19x-0.11.30.pre2.gem:The'linecache19'nativegemrequiresinstall
我有:When/^(?:|I)follow"([^"]*)"(?:within"([^"]*)")?$/do|link,selector|with_scope(selector)doclick_link(link)endend我打电话的地方:Background:GivenIamanexistingadminuserWhenIfollow"CLIENTS"我的HTML是这样的:CLIENTS我一直收到这个错误:.F-.F--U-----U(::)failedsteps(::)nolinkwithtitle,idortext'CLIENTS'found(Capybara::Element
1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,
我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions
在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主
1.1.1 YARN的介绍 为克服Hadoop1.0中HDFS和MapReduce存在的各种问题⽽提出的,针对Hadoop1.0中的MapReduce在扩展性和多框架⽀持⽅⾯的不⾜,提出了全新的资源管理框架YARN. ApacheYARN(YetanotherResourceNegotiator的缩写)是Hadoop集群的资源管理系统,负责为计算程序提供服务器计算资源,相当于⼀个分布式的操作系统平台,⽽MapReduce等计算程序则相当于运⾏于操作系统之上的应⽤程序。 YARN被引⼊Hadoop2,最初是为了改善MapReduce的实现,但是因为具有⾜够的通⽤性,同样可以⽀持其他的分布式计算模
Ruby是否有逐步调试器,类似于Perl的“perl-d”? 最佳答案 ruby-debug(对于ruby1.8),debugger(对于ruby1.9),byebug(对于ruby2.0)以及trepanning系列都有一个-x或--trace选项。在调试器内部,命令setlinetrace将打开或关闭线路跟踪。这是themanualforruby-debug原来的答案已经修改,因为数据噪声文章的链接,唉,不再有效了。还添加了ruby-debug的后继者 关于ruby-Ruby
我有一个问题。我想从另一个ruby脚本运行一个ruby脚本并捕获它的输出信息,同时让它也输出到屏幕。亚军#!/usr/bin/envrubyprint"Enteryourpassword:"password=gets.chompputs"Hereisyourpassword:#{password}"我运行的脚本文件:开始.rboutput=`runner`putsoutput.match(/Hereisyour(password:.*)/).captures[0].to_s正如您在此处看到的那样,存在问题。在start.rb的第一行,屏幕是空的。我在运行程序中看不到“输入您的密