草庐IT

Linux环境下gdb程序调试

魏天乐大帅哥 2023-07-12 原文

目录

  • 这篇文章将会介绍gdb以及一些常用的gdb调试指令;

gdb介绍

gdb是linux中的调试器,由于linux是命令行式的操作,所以要进行调试也一定是以命令行的方式进行,相比于win下vs等IDE的调试使用起来操作比较繁琐,但是程序调试的思路都是大致的。

但是在某些开发场景并没有设计专门的IDE,这种情况下是没有办法用IDE进行调试的,这个时候只能使用gdb调试了。

俗话说一名合格的程序员,大部分的时间都是在debug调试,可见熟悉gdb调试是至关重要的了!


进入gdb调试环境

  1. 创建mytest.c的源文件,并写入如下代码用于调试;

编译及运行结果:

进入gdb环境进行调试:

  • 指令:gdb + 程序名称

但是再次版本下,我们发现输入gdb指令:l 0的时候,报错:

原因是默认情况下,我们在linux下使用gcc/g++默认生成的程序都是release版本,这种发布的版本是不带调试信息的,无法进行调试,是给用户使用的;

我们需要调试,就得编译的时候带选项-g告知编译器编译debug可调式版本的程序!

我们进一步观察能发现,release版本的成虚要比debug版本更小,因为优化,抹去了调试用的信息等:


指令学习

成功进入gdb调试环境并且能够调试了,我们介绍常用指令的学习

l(list)指令

l(list):显示出可执行程序内的代码,方便观察

当我们用l指令配合一个数字的时候:l + num表示从num行开始显示代码;

此时只能显示10行代码:,接着继续按回车,就能接着显示后续的10行代码;

当我们用l指令配合两个数字(用逗号隔开)的时候:l num1,num2表示显示从num1行到num2行的代码;

当我们使用l+函数名的时候:l addToVal 表示显示addToVal函数的代码,同样每次显示10行;

b(break)指令

b + 行数: 表示在指定行添加断点(breakpoint)

break+函数名: 进入指定函数,在其作用域内第一行有效代码设置断点

在第5行和第10行加断点:

在addToVal函数第一行代码处设置断点:

info b指令

info b: 显示出所有断点的信息

d指令

d + 断点编号:删除该编号的断点


d : 删除所有的断点

(注意,断点编号不是行号,d之前需要用info查一下断点的编号Num)

r(run)指令

r(run):程序运行指令,有断点运行到第一个断点处,无断点运行整个程序;

无断点的情况下运行完了整个程序:

运行到第一个断点处:

显示断点的编号以及中断位置所处的函数名当前文件名以及断点行号

n(next)指令

n(next) : 在程序已经run的基础上,逐过程执行,遇到函数调用不会进入直接执行完毕,类似VS中Debug调试的F10

s(step)指令

s(step) :在程序已经run的基础上, 逐语句执行,遇到函数可进入函数内部观察细节,类似VS中Debug调试的F11

c(continue)指令

c(continue) : 在程序已经run的基础上,从当前断点跳跃到下一个断点处,类似于VS中Debug调试的F5

在24行addToVal()函数入口处的断点处停下,用c指令,直接跳转到了26行的断点,期间的addToVal()和Print()函数都已被执行!

bt(breaktrace)指令

bt :查看各级函数调用的栈帧信息(栈帧号和所属函数等)以及参数


由于面试被问到这个指令,做以下扩充:

  • bt(backtrace) break step next continue 这几个指令 务必清晰;是最基本常用的;

bt + 栈帧数量 --> 这对于调用栈帧比较多的情况很有用处,可以忽略掉不太关心的那些栈帧。比如执行 bt 2 ,则只显示两个栈帧。

f(frame) + 栈帧号 -->切换栈帧,每一个栈帧所对应的程序的运行上下文都不同,比如栈帧 1 的局部变量和栈帧 2 的局部变量都不相同,只有切换到某个具体的栈帧之后才能查看该栈帧对应的局部变量信息
f(frame) + 栈帧地址 -->切换栈帧; 帧地址是栈帧所对应的地址。如果程序崩溃,栈回溯信息可能会遭到破坏,这时就可以使用该命令通过栈帧地址来进行栈帧切换

i(info) + locals -->查看当前帧的所有局部变量的值
i(info) + args --> 查看当前帧所有的函数参数和值

i(info) + f(frame) + 栈帧号/地址 -->查看栈帧的详细信息

此外,gdb怎么调试多线程(每个线程有自己的handler函数,本质上也是个栈帧)?

info+thread 显示当前可调试的所有线程,拿到线程ID
thread+线程ID 切换到某个线程下,紧接着用bt查看当前线程的栈帧,break打上断点等操作

finish指令

finish: 在某个函数内部时,不想再执行该函数,可以用finish直接结束函数,从而跳出该函数,1.之后回到这个函数的调用处,等待进一步的命令;2.得到这个函数的返回值;

p(print)指令

p(print)+变量名 : 打印当前栈帧内的变量的值


p(print)+(表达式) : 打印当前战阵括号内表达式的值

display指令

display 临时变量 : 跟踪一个变量,变量常驻在屏幕上,每次停下来都显示他的值;有点像VS的监视窗口中添加监视的变量;

undisplay指令

undisplay+临时变量编号 : 使其不再常驻在屏幕上 (与display配合使用,起相反作用)

until指令

until+行号 :直接跳至指定的有效代码行,一般用于直接跳出某个循环或递归

disable命令

diable+断点号 : 禁用指定的断点


disable b: 禁用所有断点

enable命令

启用断点,和上面disable用法一样,不再描述;

有关Linux环境下gdb程序调试的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  3. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用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中编写命令行实用程序

  4. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  5. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  6. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  7. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  8. ruby-on-rails - 无法让 rspec、spork 和调试器正常运行 - 2

    GivenIamadumbprogrammerandIamusingrspecandIamusingsporkandIwanttodebug...mmm...let'ssaaay,aspecforPhone.那么,我应该把“require'ruby-debug'”行放在哪里,以便在phone_spec.rb的特定点停止处理?(我所要求的只是一个大而粗的箭头,即使是一个有挑战性的程序员也能看到:-3)我已经尝试了很多位置,除非我没有正确测试它们,否则会发生一些奇怪的事情:在spec_helper.rb中的以下位置:require'rubygems'require'spork'

  9. ruby-on-rails - 在 Rails 开发环境中为 .ogv 文件设置 Mime 类型 - 2

    我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain

  10. ruby - JetBrains RubyMine 3.2.4 调试器不工作 - 2

    使用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

随机推荐